由于之后的触摸屏驱动分析中使用到了GPIO子系统和i2c子系统,因此在分析触摸屏驱动之前我准备把这两个子系统进行简单分析。

 

之前我们使用GPIO引脚的方式并不是推荐的方式,当我们更改某一bit时,很有可能导致另外的bit值发生更改。而GPIO子系统进行了封装,确保每次只对一个GPIO引脚操作,而不会影响到别的GPIO引脚。

 

下面这段代码是我从驱动程序中摘出来的,它首先获取GPIO引脚,之后设置为输出模式。

 1 ret = gpio_request(EXYNOS4_GPL0(2), "TP1_EN");
 2 if (ret) {
 3     printk(KERN_ERR "failed to request TP1_EN for I2C control\n");
 4     //return err;
 5 }
 6 
 7 gpio_direction_output(EXYNOS4_GPL0(2), 1);
 8 
 9 s3c_gpio_cfgpin(EXYNOS4_GPL0(2), S3C_GPIO_OUTPUT);
10 gpio_free(EXYNOS4_GPL0(2));
11 
12 mdelay(5);

 

 

gpio_direction_output()方便我们操作GPIO引脚,我们来看一下gpio_direction_output()函数会做些什么。

 1 int gpio_direction_output(unsigned gpio, int value)
 2 {
 3     unsigned long        flags;
 4     struct gpio_chip    *chip;    /* 不同单板对应不同chip,由芯片厂实现 */
 5     struct gpio_desc    *desc = &gpio_desc[gpio];
 6     int            status = -EINVAL;
 7 
 8     spin_lock_irqsave(&gpio_lock, flags);
 9     /* 判断gpio是否可用 */
10     if (!gpio_is_valid(gpio))
11         goto fail;
12     chip = desc->chip;
13     if (!chip || !chip->set || !chip->direction_output)
14         goto fail;
15     gpio -= chip->base;
16     if (gpio >= chip->ngpio)
17         goto fail;
18     status = gpio_ensure_requested(desc, gpio);
19     if (status < 0)
20         goto fail;
21 
22     /* now we know the gpio is valid and chip won't vanish */
23 
24     spin_unlock_irqrestore(&gpio_lock, flags);
25 
26     might_sleep_if(chip->can_sleep);
27 
28     if (status) {
29         status = chip->request(chip, gpio);
30         if (status < 0) {
31             pr_debug("GPIO-%d: chip request fail, %d\n",
32                 chip->base + gpio, status);
33             /* and it's not available to anyone else ...
34              * gpio_request() is the fully clean solution.
35              */
36             goto lose;
37         }
38     }
39     /* 调用chip的direction_output()函数 */
40     status = chip->direction_output(chip, gpio, value);
41     if (status == 0)
42         set_bit(FLAG_IS_OUT, &desc->flags);
43     trace_gpio_value(chip->base + gpio, 0, value);
44     trace_gpio_direction(chip->base + gpio, 0, status);
45 lose:
46     return status;
47 fail:
48     spin_unlock_irqrestore(&gpio_lock, flags);
49     if (status)
50         pr_debug("%s: gpio-%d status %d\n",
51             __func__, gpio, status);
52     return status;
53 }
54 EXPORT_SYMBOL_GPL(gpio_direction_output);

 

通过代码第4行struct gpio_chip,我们可以推断出此结构体是内核提供给各个板商的,用于其实现不同GPIO引脚操作。

在drivers/gpio/目录下,有跟平台相关的文件,这些文件就是由厂商提供的GPIO引脚操作函数。在此我以gpio-omap.c为例进行讨论

我们先来查看probe()函数:

13、GPIO子系统
 1 static int __devinit omap_gpio_probe(struct platform_device *pdev)
 2 {
 3     static int gpio_init_done;
 4     struct omap_gpio_platform_data *pdata;
 5     struct resource *res;
 6     int id;
 7     struct gpio_bank *bank;
 8 ...
 9     pdata = pdev->dev.platform_data;
10 ...
11     ret = init_gpio_info(pdev);
12 ...
13     id = pdev->id;
14     bank = &gpio_bank[id];
15     
16     res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
17 ...
18     bank->irq = res->start;
19     bank->virtual_irq_start = pdata->virtual_irq_start;
20     bank->method = pdata->bank_type;
21     bank->dev = &pdev->dev;
22     bank->dbck_flag = pdata->dbck_flag;
23     bank->stride = pdata->bank_stride;
24     bank_width = pdata->bank_width;
25 
26     spin_lock_init(&bank->lock);
27 
28     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
29 
30     bank->base = ioremap(res->start, resource_size(res));
31 ...
32     omap_gpio_mod_init(bank, id);
33     omap_gpio_chip_init(bank);
34     omap_gpio_show_rev(bank);
35 
36     if (!gpio_init_done)
37         gpio_init_done = 1;
38 
39     return 0;
40 }
View Code

相关文章: