Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1651951
  • 博文数量: 245
  • 博客积分: 10378
  • 博客等级: 上将
  • 技术积分: 2571
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-27 08:19
文章分类

全部博文(245)

文章存档

2013年(4)

2012年(8)

2011年(13)

2010年(68)

2009年(152)

分类: LINUX

2010-03-26 23:25:45

在mini2440的驱动中,如果要对GPIO进行相关功能的配置和数据的写入获取,需要直接对相应的寄存器进行操作,其中使用的函数有:
 
mini2440中端口号的形成可以使用下边的宏:
S3C2410_GPn(m),获得n组io的第m个端口
例如:
S3C2410_GPB(5);使用宏可以很方便的进行操作。
在S3C2440中的GPIO通常有第二功能,在配置IO口功能的时候需要使用如下的宏定义:

#define S3C2410_GPIO_LEAVE  (0xFFFFFFFF)
#define S3C2410_GPIO_INPUT  (0xFFFFFFF0)    /* not available on A */
#define S3C2410_GPIO_OUTPUT (0xFFFFFFF1)
#define S3C2410_GPIO_IRQ    (0xFFFFFFF2)    /* not available for all */
#define S3C2410_GPIO_SFN2   (0xFFFFFFF2)    /* bank A => addr/cs/nand */
#define S3C2410_GPIO_SFN3   (0xFFFFFFF3)    /* not available on A */

上述宏要注意数据内容,S3C2410_GPIO功能配置在各个IO是不一样的,有些IO口使用一位寄存器来配置,而有些寄存器使用2位寄存器来设置,但使用上述宏定义之后,就可以很方便的配置IO,而不用计较到底是2位还是1位寄存器。
 
 
s3c2410_gpio_cfgpin(端口号,输入/输出/第二功能)
 

void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
    void __iomem *base = S3C24XX_GPIO_BASE(pin);
    unsigned long mask;
    unsigned long con;
    unsigned long flags;

    if (pin < S3C2410_GPIO_BANKB) {
        mask = 1 << S3C2410_GPIO_OFFSET(pin);
    } else {
        mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
    }

    switch (function) {
    case S3C2410_GPIO_LEAVE:
        mask = 0;
        function = 0;
        break;

    case S3C2410_GPIO_INPUT:
    case S3C2410_GPIO_OUTPUT:
    case S3C2410_GPIO_SFN2:
    case S3C2410_GPIO_SFN3:
        if (pin < S3C2410_GPIO_BANKB) {
            function -= 1;
            function &= 1;
            function <<= S3C2410_GPIO_OFFSET(pin);
        } else {
            function &= 3;
            function <<= S3C2410_GPIO_OFFSET(pin)*2;
        }
    }

s3c2410_gpio_setpin(端口号,数据) 对相应的端口置位 

void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{
    void __iomem *base = S3C24XX_GPIO_BASE(pin);
    unsigned long offs = S3C2410_GPIO_OFFSET(pin);
    unsigned long flags;
    unsigned long dat;

    local_irq_save(flags);

    dat = __raw_readl(base + 0x04);
    dat &= ~(1 << offs);
    dat |= to << offs;
    __raw_writel(dat, base + 0x04);

    local_irq_restore(flags);
}

s3c2410_gpio_setpin(端口号)  会的相应端口的数据,通过函数返回值的形式获得。
 

unsigned int s3c2410_gpio_getpin(unsigned int pin)
{
    void __iomem *base = S3C24XX_GPIO_BASE(pin);
    unsigned long offs = S3C2410_GPIO_OFFSET(pin);

    return __raw_readl(base + 0x04) & (1<< offs);
}

 

例如: 

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>


#define DEVICE_NAME "leds"

// 要使用的IO口
static unsigned long led_table [] = {
    S3C2410_GPB(5),
    S3C2410_GPB(6),
    S3C2410_GPB(7),
    S3C2410_GPB(8),
};

// 相应IO口功能的配置
static unsigned int led_cfg_table [] = {
    S3C2410_GPIO_OUTPUT,
    S3C2410_GPIO_OUTPUT,
    S3C2410_GPIO_OUTPUT,
    S3C2410_GPIO_OUTPUT,
};

static int sbc2440_leds_ioctl(
    struct inode *inode,
    struct file *file,
    unsigned int cmd,
    unsigned long arg)
{
    switch(cmd) {
    case 0:
    case 1:
        if (arg > 4) {
            return -EINVAL;
        }

        // IO口赋值
        s3c2410_gpio_setpin(led_table[arg], !cmd);
        return 0;
    default:
        return -EINVAL;
    }
}

static struct file_operations dev_fops = {
    .owner    =    THIS_MODULE,
    .ioctl    =    sbc2440_leds_ioctl,
};

static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};

static int __init dev_init(void)
{
    int ret;

    int i;
    
    for (i = 0; i < 4; i++) {

       //设置IO口功能
        s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
        // 对应IO口赋值为0

       s3c2410_gpio_setpin(led_table[i], 0);
    }

    ret = misc_register(&misc);

    printk (DEVICE_NAME"\tinitialized\n");

    return ret;
}

static void __exit dev_exit(void)
{
    misc_deregister(&misc);
}

module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("FriendlyARM Inc.");


阅读(5106) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~