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);写数据寄存器
这里有个疑问,为何要写两次数据寄存器?
上面这两个函数都和上一篇分析的函数类似,可以说一样,就不再重复了。看下下面这两个函数:
这两个函数是针对数据寄存器的,所以对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;
}