您的位置:首页 > 运维架构 > Linux

Linux下s3c6410的GPIO操作(2)

2012-05-13 10:57 1101 查看
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)的链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: