Linux下s3c6410的GPIO操作(5)

1、我们曾经在前面看到这个函数,源码如下:

__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
{
struct gpio_chip *gc = &chip->chip;
int ret;


BUG_ON(!chip->base);
BUG_ON(!gc->label);
BUG_ON(!gc->ngpio);


if (!gc->direction_input)
gc->direction_input = s3c_gpiolib_input;
if (!gc->direction_output)
gc->direction_output = s3c_gpiolib_output;
if (!gc->set)
gc->set = s3c_gpiolib_set;
if (!gc->get)
gc->get = s3c_gpiolib_get;

当初只是对这一部分,说明gc内部成员的赋值,而没具体分析这几个函数,我里的几个函数并不是对每个GPIO都实用,有些我们定义了新的函数,所以并不用这些默认值,希望你能分清,那些用的是默认值,哪些是我们新定义的。我们现在分析下。

/* gpiochip_add() prints own failure message on error. */
ret = gpiochip_add(gc);
if (ret >= 0)
s3c_gpiolib_track(chip);

}

2、这几个函数的源码都在linux/arch/arm/plat-s3c/gpio.c文件中:


/* Default routines for controlling GPIO, based on the original S3C24XX
 * GPIO functions which deal with the case where each gpio bank of the
 * chip is as following:
 *
 * base + 0x00: Control register, 2 bits per gpio
 *        gpio n: 2 bits starting at (2*n)
 * 00 = input, 01 = output, others mean special-function

以前是4位,现在是2位,区别就在这里
 * base + 0x04: Data register, 1 bit per gpio
 * bit n: data bit n
*/

static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
void __iomem *base = ourchip->base; 这些都和前面一样

unsigned long flags;
unsigned long con;


local_irq_save(flags);


con = __raw_readl(base + 0x00);
con &= ~(3 << (offset * 2));


__raw_writel(con, base + 0x00);


local_irq_restore(flags);
return 0;
}



static int s3c_gpiolib_output(struct gpio_chip *chip,
     unsigned offset, int value)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
void __iomem *base = ourchip->base;
unsigned long flags;
unsigned long dat;
unsigned long con;


local_irq_save(flags);


dat = __raw_readl(base + 0x04);
dat &= ~(1 << offset);
if (value)
dat |= 1 << offset;
__raw_writel(dat, base + 0x04);


con = __raw_readl(base + 0x00);
con &= ~(3 << (offset * 2));
con |= 1 << (offset * 2);


__raw_writel(con, base + 0x00);
__raw_writel(dat, base + 0x04);

这个是我上一篇是疑问的地方,我把它从新复制过来,在下面,对比下:

__raw_writel(dat, base + OFF_GPDAT);写数据寄存器
__raw_writel(con, base + OFF_GPCON);写控制寄存器
__raw_writel(dat, base + OFF_GPDAT);写数据寄存器

    这里有个疑问,为何要写两次数据寄存器?



local_irq_restore(flags);
return 0;
}

上面这两个函数都和上一篇分析的函数类似,可以说一样,就不再重复了。看下下面这两个函数:

这两个函数是针对数据寄存器的,所以对4位,2位的控制寄存器都实用,因为数据寄存器中1位表示一个IO口,大家都一样,所以没必要特殊化。当然,使用的场合就有所不同,我想一般在设置为输出的时候才需要对某一位设置成1或者0吧?在设置为输入的时候,才需要读取吧?函数很简单,就不分析了。

static void s3c_gpiolib_set(struct gpio_chip *chip,
   unsigned offset, int value)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
void __iomem *base = ourchip->base;
unsigned long flags;
unsigned long dat;


local_irq_save(flags);


dat = __raw_readl(base + 0x04);
dat &= ~(1 << offset);
if (value)
dat |= 1 << offset;
__raw_writel(dat, base + 0x04);


local_irq_restore(flags);
}



static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
{
struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
unsigned long val;


val = __raw_readl(ourchip->base + 0x04);
val >>= offset;
val &= 1;


return val;
}

你可能感兴趣的:(c,linux,struct,input,each,output)