Linux下s3c6410的GPIO操作(2)

1、还接着看上一篇的这个函数

arch_initcall(s3c64xx_gpiolib_init);

static __init int s3c64xx_gpiolib_init(void)

{
s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
   s3c64xx_gpiolib_add_4bit);


s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
   s3c64xx_gpiolib_add_4bit2);


s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), NULL);


return 0;
}

此函数用来初始化GPIO的信息,分三次调用s3c64xx_gpiolib_add函数把三组GPIO端口加入到信息表中。

2、s3c64xx_gpiolib_add函数源码在同一个文件中,如下:

static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
     int nr_chips,数目
     void (*fn)(struct s3c_gpio_chip *))传入的函数,在下面调用
{
for (; nr_chips > 0; nr_chips--, chips++) { 循环
if (fn)
(fn)(chips);
s3c_gpiolib_add(chips);
}

}

看上面的s3c64xx_gpiolib_init函数可知传入的实参,源码如下:

static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
{
chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;

}

static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
{
chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;

}

3、回到s3c64xx_gpiolib_add函数中,接着看,该轮到s3c_gpiolib_add(chips)这个函数了,源码如下:

__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
{
struct gpio_chip *gc = &chip->chip; 得到对应的gpio_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;

这段是先判断是否提供了相应的函数,如果没有就用默认的函数进行初始化。如果不明,会过去看2或者找到gpio_chip结构体,看一下其内部的成员。

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

}

看一下蓝色的那部分,gpiochip_add函数源码如下:

先看下注释:

/**
 * gpiochip_add() - register a gpio_chip说明了这个函数的目地
 * @chip: the chip to register, with chip->base initialized
 * Context: potentially before irqs or kmalloc will work
 *
 * Returns a negative errno if the chip can't be registered, such as
 * because the chip->base is invalid or already associated with a
 * different chip.  Otherwise it returns zero as a success code.返回值
 *
 * When gpiochip_add() is called very early during boot, so that GPIOs
 * can be freely used, the chip->dev device must be registered before
 * the gpio framework's arch_initcall().  Otherwise sysfs initialization
 * for GPIOs will fail rudely. 和sysfs有关,我们暂不关心

 *
 * If chip->base is negative, this requests dynamic assignment of
 * a range of valid GPIOs.

 */
int gpiochip_add(struct gpio_chip *chip)
{
unsigned long flags;
int status = 0;
unsigned id;
int base = chip->base;


if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))
&& base >= 0) {进行GPIO范围的判断,是否是正确的IO

status = -EINVAL;
goto fail;
}


spin_lock_irqsave(&gpio_lock, flags); 锁


if (base < 0) {
base = gpiochip_find_base(chip->ngpio);
if (base < 0) {
status = base;
goto unlock;
}
chip->base = base;
}

对应上面的那段注释,此情景中,base>0,那么这个base到底是什么,又在何时赋值的呢?看下面:

                .base= S3C64XX_GPQ_BASE,
.config = &gpio_2bit_cfg_eint11,
.chip = {
.base = S3C64XX_GPQ(0),这就是上面的那个base,应该指的是GPIO的编号。
.ngpio = S3C64XX_GPIO_Q_NR,
.label = "GPQ",
}


/* these GPIO numbers must not be managed by another gpio_chip*/GPIO的编号不能被其他gpio_chip结构体使用
for (id = base; id < base + chip->ngpio; id++) {
if (gpio_desc[id].chip != NULL) {
status = -EBUSY;
break;
}
}

这段中的gpio_desc是什么?看下面:

struct gpio_desc {
struct gpio_chip*chip;
unsigned long flags;
/* flag symbols are bit numbers */
#define FLAG_REQUESTED 0
#define FLAG_IS_OUT 1
#define FLAG_RESERVED 2
#define FLAG_EXPORT 3/* protected by sysfs_lock */
#define FLAG_SYSFS 4/* exported via /sys/class/gpio/control */


#ifdef CONFIG_DEBUG_FS
const char *label;
#endif
};

static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];

对于s3c6410中有

/* define the number of gpios we need to the one after the GPQ() range */
#define ARCH_NR_GPIOS (S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)


if (status == 0) {
for (id = base; id < base + chip->ngpio; id++) {
gpio_desc[id].chip = chip;

这段应该是使gpio_desc结构体与gpio_chip结构体对应起来,其中gpio_desc是以GPIO的编号为下标的数组,通过gpio_chip结构体就可以找到对应的struct s3c_gpio_chip结构体,这样关于GPIO的三个结构体就对应起来了。


/* REVISIT:  most hardware initializes GPIOs as
* inputs (often with pullups enabled) so power
* usage is minimized.  Linux code should set the
* gpio direction first thing; but until it does,
* we may expose the wrong direction in sysfs.
*/
gpio_desc[id].flags = !chip->direction_input
? (1 << FLAG_IS_OUT)
: 0;

}
}


unlock:
spin_unlock_irqrestore(&gpio_lock, flags);
if (status == 0)
status = gpiochip_export(chip);这个函数是干啥的呢?源码如下:大致看了下,应该与sysfs文件系统有关,在这里我们不关心。

static int gpiochip_export(struct gpio_chip *chip)
{
int status;
struct device *dev;


/* Many systems register gpio chips for SOC support very early,
* before driver model support is available.  In those cases we
* export this later, in gpiolib_sysfs_init() ... here we just
* verify that _some_ field of gpio_class got initialized.
*/
if (!gpio_class.p)
return 0;


/* use chip->base for the ID; it's already known to be unique */
mutex_lock(&sysfs_lock);
dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
"gpiochip%d", chip->base);
if (dev) {
status = sysfs_create_group(&dev->kobj,
&gpiochip_attr_group);
} else
status = -ENODEV;
chip->exported = (status == 0);
mutex_unlock(&sysfs_lock);


if (status) {
unsigned long flags;
unsigned gpio;


spin_lock_irqsave(&gpio_lock, flags);
gpio = chip->base;
while (gpio_desc[gpio].chip == chip)
gpio_desc[gpio++].chip = NULL;
spin_unlock_irqrestore(&gpio_lock, flags);


pr_debug("%s: chip %s status %d\n", __func__,
chip->label, status);
}


return status;
}

下面这段是错误处理。

fail:
/* failures here can mean systems won't boot... */
if (status)
pr_err("gpiochip_add: gpios %d..%d (%s) not registered\n",
chip->base, chip->base + chip->ngpio - 1,
chip->label ? : "generic");
return status;
}

Linux下s3c6410的GPIO操作(1)的链接

Linux下s3c6410的GPIO操作(3)的链接



你可能感兴趣的:(c,linux,struct,output,initialization,Numbers)