1、还接着看上一篇的这个函数
arch_initcall(s3c64xx_gpiolib_init);
static __init int s3c64xx_gpiolib_init(void)
{此函数用来初始化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)的链接