Linux下s3c6410的GPIO操作(6)

1、在  Linux下s3c6410的GPIO操作(3) 这篇博客中少分析了一个函数,当时列出了源码,但没分析,现在补上。

什么函数呢?如下所示:

#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX

/**
 * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
 * @chip: The gpio chip that is being configured.
 * @off: The offset for the GPIO being configured.
 * @cfg: The configuration value to set.

 *
 * This helper deal with the GPIO cases where the control register has 4 bits
 * of control per GPIO, generally in the form of:
 * 0000 = Input
 * 0001 = Output
 * others = Special functions (dependant on bank)
int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
unsigned int off, unsigned int cfg)
{
void __iomem *reg = chip->base;

得到GPIO端口控制寄存器的基地址,不同的端口可能不同哦!如下所示:

(第一种)、

static struct s3c_gpio_chip gpio_4bit[] = {
{
.base =S3C64XX_GPA_BASE,
.config = &gpio_4bit_cfg_eint0111,
.chip = {
.base = S3C64XX_GPA(0),
.ngpio = S3C64XX_GPIO_A_NR,
.label = "GPA",
}

(第二种)

static struct s3c_gpio_chip gpio_4bit2[] = {
{
.base =S3C64XX_GPH_BASE + 0x4,
.config = &gpio_4bit_cfg_eint0111,
.chip = {
.base = S3C64XX_GPH(0),
.ngpio = S3C64XX_GPIO_H_NR,
.label = "GPH",
}

(第三种)、

static struct s3c_gpio_chip gpio_2bit[] = {
{
.base = S3C64XX_GPF_BASE,
.config = &gpio_2bit_cfg_eint11,
.chip = {
.base = S3C64XX_GPF(0),
.ngpio = S3C64XX_GPIO_F_NR,
.label = "GPF",
}

既然端口分三种,那么对应的操作函数也应该分为三种,但实际上分成了两种,按控制寄存器的控制位数分为4和2.

这两种操作函数分别是s3c_gpio_setcfg_s3c64xx_4bit函数和s3c_gpio_setcfg_s3c24xx函数。


unsigned int shift = (off & 7) * 4;
u32 con;


if (off < 8 && chip->chip.ngpio > 8)
reg -= 4;

这个判断是为4-2这种情况准备的,因为上面的基地址是第二个控制寄存器的基地址,所以要减去4得到第一个控制寄存器的基地址。可以这样进行判断,一个很重要的原因就是下面这个表,观察一下,是否发现4Bit类型的都没有超过8个。所以我才说这个是针对4-2这种情况的。

/* GPIO bank summary:
 *
 * Bank GPIOs Style SlpCon ExtInt Group
 * A 8 4Bit Yes 1
 * B 7 4Bit Yes 1
 * C 8 4Bit Yes 2
 * D 5 4Bit Yes 3
 * E 5 4Bit Yes None
 * F 16 2Bit Yes 4 [1]
 * G 7 4Bit Yes 5
 * H 10 4Bit[2] Yes 6
 * I 16 2Bit Yes None
 * J 12 2Bit Yes None
 * K 16 4Bit[2] No None
 * L 15 4Bit[2] No None
 * M 6 4Bit No IRQ_EINT
 * N 16 2Bit No IRQ_EINT
 * O 16 2Bit Yes 7
 * P 15 2Bit Yes 8
 * Q 9 2Bit Yes 9
 *
 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
 * [2] BANK has two control registers, GPxCON0 and GPxCON1
 */


if (s3c_gpio_is_cfg_special(cfg)) {
cfg &= 0xf;
cfg <<= shift;
}


#define s3c_gpio_is_cfg_special(_cfg) \
(((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)

#define S3C_GPIO_SPECIAL_MARK(0xfffffff0)

主要目的是为了判断传入的 unsigned int cfg这个参数,这个参数的之可以为0xfffffffx,其中x有下表所示:



当然,也可以传入的参数直接为上表中的数值,看开头的注释,就可以明白了。

con = __raw_readl(reg);
con &= ~(0xf << shift);
con |= cfg;
__raw_writel(con, reg);
这一部分很简单,无非就是读后,再写。

return 0;
}

注:如果大家对上面的shift的处理不是很明白,可以举个实际例子。如9的时候,unsigned int shift = (off & 7) * 4;的shift为1,别忘了现在是对第二个控制寄存器操作,0-7是第一个寄存器,8以后是第二个寄存器,那9就是第二个控制寄存器的第二个控制段,也就是第二个4位,这么说应该明白了吧。
#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */

2、

上面说的是两个函数中的其中一个,现在来说第二个,s3c_gpio_setcfg_s3c24xx,源码如下:

/**
 * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
 * @chip: The gpio chip that is being configured.
 * @off: The offset for the GPIO being configured.
 * @cfg: The configuration value to set.
 *

 * This helper deal with the GPIO cases where the control register
 * has two bits of configuration per gpio, which have the following
 * functions:
 * 00 = input
 * 01 = output
 * 1x = special function

*/



int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
   unsigned int off, unsigned int cfg)
{
void __iomem *reg = chip->base;
unsigned int shift = off * 2;

u32 con;


if (s3c_gpio_is_cfg_special(cfg)) {
cfg &= 0xf;
if (cfg > 3)
return -EINVAL;


cfg <<= shift;
}


con = __raw_readl(reg);
con &= ~(0x3 << shift);
con |= cfg;
__raw_writel(con, reg);



return 0;
}

和上面那个函数一样,而且还相对简单,就不分析了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值