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

#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);
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sanzhong104204

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值