#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);
}
s3c2410_gpio_cfgpin 、s3c2410_gpio_setpin函数分析 --linux(tq2440开发板)的gpio驱动分析
最新推荐文章于 2021-05-06 11:35:18 发布