您的位置:首页 > 运维架构 > Linux

s3c2410_gpio_cfgpin 、s3c2410_gpio_setpin函数分析 --linux(tq2440开发板)的gpio驱动分析

2013-04-01 12:11 609 查看
#define S3C2410_GPIO_BANKA   (32*0)
#define S3C2410_GPIO_BANKB   (32*1)
#define S3C2410_GPIO_BANKC   (32*2)

//获取引脚相对于所有GPIO的起始地址的偏移量
#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))

//S3C2410_GPIONO用来获取gpio引脚相对于GPIO基地址即0X5600_0000的偏移量
#define S3C2410_GPB5         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)

//获取gpio引脚所在GPIO组的第一个寄存器即GPXCON的虚拟地址
#define S3C24XX_GPIO_BASE(x)  S3C2410_GPIO_BASE(x)
#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)

//获取引脚所在GPIO组相对于GPIO基地址的偏移量
#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)

//GPB5的功能配置
#define S3C2410_GPB5_INP     (0x00 << 10) //输入口
#define S3C2410_GPB5_OUTP    (0x01 << 10) //输出口
#define S3C2410_GPB5_nXBACK  (0x02 << 10) //nXBACK功能

//配置引脚为指定的功能
//pin~引脚相对于GPIO_VA_BASE的偏移量,function~待配置的功能
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
//base存储了GPXCON寄存器的地址
void __iomem *base = S3C24XX_GPIO_BASE(pin);

unsigned long mask;//mask 为1的位是需要配置的位
unsigned long con;
unsigned long flags;

if (pin < S3C2410_GPIO_BANKB) {
//GPA口每位用1bit来进行配置
mask = 1 << S3C2410_GPIO_OFFSET(pin);
} else {
//GPB~GPJ口每位用2bit来进行配置
mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
}

//仅适用于配置整组GPIO口时的switch
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;
}
}

/* modify the specified register wwith IRQs off */

//保存irq状态
local_irq_save(flags);

//读控制寄存器
con  = __raw_readl(base + 0x00);

//清除需要配置的位
con &= ~mask;

//重新配置相关位
con |= function;

//写控制寄存器
__raw_writel(con, base + 0x00);
//恢复irq状态
local_irq_restore(flags);
}

//设置引脚位电平
void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{

//base存储了GPXCON寄存器的地址
void __iomem *base = S3C24XX_GPIO_BASE(pin);

//offs为引脚所在GPIO组相对于GPIO基地址的偏移量
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long dat;

//保存irq状态
local_irq_save(flags);

//读取GPXDAT寄存器的值
dat = __raw_readl(base + 0x04);

//修改GPXDAT值
dat &= ~(1 << offs);
dat |= to << offs;

//写回到GPXDAT寄存器
__raw_writel(dat, base + 0x04);

//恢复irq状态
local_irq_restore(flags);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  gpio