Chinaunix首页 | 论坛 | 博客
  • 博客访问: 240939
  • 博文数量: 54
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 431
  • 用 户 组: 普通用户
  • 注册时间: 2014-07-26 09:36
文章分类

全部博文(54)

分类: LINUX

2014-08-29 23:33:12

原文地址:gpio_request 原形代码 作者:xingfuhaitun

http://blog.csdn.net/maopig/article/details/7428561

其原型为 int gpio_request(unsigned gpio, const char *label) 先说说其参数,gpio则为你要申请的哪一个管脚,label则是为其取一个名字。其具体实现如下

点击(此处)折叠或打开

  1. int gpio_request(unsigned gpio, const char *label)
  2. {
  3.         struct gpio_desc *desc;//这个自己看源码
  4.         struct gpio_chip *chip;//这个自己看源码
  5.         int status = -EINVAL;
  6.         unsigned long flags;
  7.         spin_lock_irqsave(&gpio_lock, flags);//屏蔽中断
  8.         if (!gpio_is_valid(gpio))//判断是否有效,也就是参数的取值范围判断
  9.              goto done;
  10.         desc = &gpio_desc[gpio];
  11. //这个是关键gpio_desc为定义的一个全局的数组变量,这个函数的实值也就是,
  12. //用gpio_desc里面的一个变量来表示数组中的这个元素已经被申请了,而这个变量就是下面会看到的desc->flags。
  13. chip = desc->chip;//按理说这个这个全局的gpio_desc如果没有初始化的话,这个chip就为空了,随后就直接返回-EINVAL了。
  14. if (chip == NULL)如果不为空继续往下走
  15.   goto done;
  16. if (!try_module_get(chip->owner))
  17.   goto done;
  18. /* NOTE: gpio_request() can be called in early boot,
  19.   * before IRQs are enabled, for non-sleeping (SOC) GPIOs.
  20.   */
  21. if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
  22. //这里测试并设置flags的第FLAG_REQUESTED位,如果没有被申请就返回该位的原值0,分析到这儿,也差不多满足了我的个人要求。
  23.   desc_set_label(desc, label ? : "?");
  24.   status = 0;
  25. } else {
  26.   status = -EBUSY;
  27.   module_put(chip->owner);
  28.   goto done;
  29. }
  30. if (chip->request) {
  31.   /* chip->request may sleep */
  32.   spin_unlock_irqrestore(&gpio_lock, flags);
  33.   status = chip->request(chip, gpio - chip->base);
  34.   spin_lock_irqsave(&gpio_lock, flags);
  35.   if (status < 0) {
  36.    desc_set_label(desc, NULL);
  37.    module_put(chip->owner);
  38.    clear_bit(FLAG_REQUESTED, &desc->flags);
  39.   }
  40. }
  41. done:
  42. if (status)
  43.   pr_debug("gpio_request: gpio-%d (%s) status %d\n",
  44.    gpio, label ? : "?", status);
  45. spin_unlock_irqrestore(&gpio_lock, flags);
  46. return status;
  47. }

davinci 平台: 

点击(此处)折叠或打开

  1. /*
  2. * TI DaVinci GPIO Support
  3. *
  4. * Copyright (c) 2006 David Brownell
  5. * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. */

  12. #include <linux/errno.h>
  13. #include <linux/kernel.h>
  14. #include <linux/list.h>
  15. #include <linux/module.h>
  16. #include <linux/err.h>
  17. #include <linux/bitops.h>

  18. #include <asm/irq.h>
  19. #include <asm/io.h>
  20. #include <asm/hardware/clock.h>

  21. #include <asm/arch/irqs.h>
  22. #include <asm/arch/hardware.h>
  23. #include <asm/arch/gpio.h>
  24. #include <asm/arch/cpu.h>

  25. #include <asm/mach/irq.h>

  26. /*
  27. 该文件实现了gpio的各种应用功能和向内核注册gpio的中断例程等功能。
  28. 用户的驱动程序可调用gpio_request和gpio_free使用或释放该gpio,
  29. 可以调用gpio_direction_input和gpio_direction_output函数设置gpio输入输出方向,
  30. 调用gpio_get_value和gpio_set_value获取设置值。
  31. */

  32. static DEFINE_SPINLOCK(gpio_lock);

  33. /* 总共有DAVINCI_N_GPIO(71)个gpio引脚,故使用相应多的bit来记录这些引脚的使用状态 */
  34. static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);

  35. /*
  36. 申请一个gpio,其实就是检查该gpio是否空闲,如果空闲就可以使用并将该gpio相应的bit置位
  37. (在gpio_in_use中)。
  38. */
  39. int gpio_request(unsigned gpio, const char *tag)
  40. {
  41.     if (gpio >= DAVINCI_N_GPIO)
  42.         return -EINVAL;
  43.     if (test_and_set_bit(gpio, gpio_in_use))
  44.         return -EBUSY;
  45.     return 0;
  46. }
  47. EXPORT_SYMBOL(gpio_request);

  48. /*
  49. 释放一个gpio,其实就是清除gpio相应的控制bit位(在gpio_in_use中)。
  50. */
  51. void gpio_free(unsigned gpio)
  52. {
  53.     if (gpio >= DAVINCI_N_GPIO)
  54.         return;
  55.     clear_bit(gpio, gpio_in_use);
  56. }
  57. EXPORT_SYMBOL(gpio_free);

  58. /* 获得gpio_controller结构体指针,gpio_controller结构体是gpio的核心控制单元,里面包含
  59. gpio的设置和数据寄存器。该结构体和__gpio_to_controller函数在/include/asm-arm/
  60. arch-davinci/gpio.h中定义,具体如下:
  61. struct gpio_controller {
  62.     u32 dir;
  63.     u32 out_data;
  64.     u32 set_data;
  65.     u32 clr_data;
  66.     u32 in_data;
  67.     u32 set_rising;
  68.     u32 clr_rising;
  69.     u32 set_falling;
  70.     u32 clr_falling;
  71.     u32 intstat;
  72. };

  73. static inline struct gpio_controller *__iomem
  74. __gpio_to_controller(unsigned gpio)
  75. {
  76.     void *__iomem ptr;
  77.     if (gpio >= DAVINCI_N_GPIO)
  78.         return NULL;

  79.     if (gpio < 32)
  80.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
  81.     else if (gpio < 64)
  82.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
  83.     else if (gpio < 96)
  84.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
  85.     else
  86.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x88);
  87.     return ptr;
  88. }
  89. 由上面的定义和ti的SPRUE25.pdf手册可以看出,__gpio_to_controller函数返回的是
  90. gpio_controller结构体到第一个成员dir的虚拟地址。获取了这个结构体指针后,
  91. 便可以控制相应的gpio了。dm644x共有71个gpio,
  92. 所以使用三个gpio_controller结构体控制,关于这个后面会由更详细的分析,
  93. */
  94. /* create a non-inlined version */
  95. static struct gpio_controller *__iomem gpio2controller(unsigned gpio)
  96. {
  97.     return __gpio_to_controller(gpio);
  98. }

  99. /*
  100. 向某个gpio设置值,0或1。如果向gpio写1,则向set_data寄存器相应的位置1,如果写0,
  101. 则向clr_data寄存器相应的位置1.__gpio_mask函数在gpio.h中定义,定义如下,
  102. static inline u32 __gpio_mask(unsigned gpio)
  103. {
  104.     return 1 << (gpio % 32);
  105. }
  106. 因为71个引脚由3个结构体控制,第一个控制前32个gpio,第二个控制次32个gpio,
  107. 最后一个控制剩余的7个gpio,故__gpio_mask函数的作用是找到在其相应控制结构体里的偏移数,
  108. 比如gpio34,那么其由第二个结构体控制,在这个机构体里的偏移是3(从0开始算,就是第二位)。
  109. 使用这个函数之前,必须确认该gpio设置成输出模式。
  110. */
  111. /*
  112. * Assuming the pin is muxed as a gpio output, set its output value.
  113. */
  114. void __gpio_set(unsigned gpio, int value)
  115. {
  116.     struct gpio_controller *__iomem g = gpio2controller(gpio);
  117.     // 设置gpio的值
  118.     __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);
  119. }
  120. EXPORT_SYMBOL(__gpio_set);

  121. /*
  122. 通过读取in_data寄存器相应该gpio的位来读取gpio的值。
  123. 使用这个函数之前,必须确认该gpio设置成输入模式,否则获得到值不可预料。
  124. */
  125. /*
  126. * Read the pin's value (works even if it's set up as output);
  127. * returns zero/nonzero.
  128. *
  129. * Note that changes are synched to the GPIO clock, so reading values back
  130. * right after you've set them may give old values.
  131. */
  132. int __gpio_get(unsigned gpio)
  133. {
  134.     struct gpio_controller *__iomem g = gpio2controller(gpio);
  135.     /* 读取gpio的值,!!的目的是使得返回的值为0或1.*/
  136.     return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
  137. } }
  138. EXPORT_SYMBOL(__gpio_get);

  139. /*
  140. 通过dir寄存器相应该gpio的位来设置gpio输入输出方向,为0,则设置成输出,为1,则设置出输入。
  141. 该函数是设置成输入,故设置dir寄存器为1.
  142.  正如应为所说的,必须确认该引脚是作为gpio功能,而不是某个模块到功能,比如spi。通过PINMUX0
  143. 和PINMUX1两个寄存器来设置。
  144. */
  145. /*--------------------------------------------------------------------------*/

  146. /*
  147. * board setup code *MUST* set PINMUX0 and PINMUX1 as
  148. * needed, and enable the GPIO clock.
  149. */
  150. int gpio_direction_input(unsigned gpio)
  151. {
  152.     struct gpio_controller *__iomem g = gpio2controller(gpio);
  153.     u32 temp;
  154.     u32 mask;

  155.     if (!g)
  156.         return -EINVAL;
  157.     spin_lock(&gpio_lock);
  158.     mask = __gpio_mask(gpio);
  159.     temp = __raw_readl(&g->dir);
  160.     temp |= mask; // 设置成1
  161.     __raw_writel(temp, &g->dir); // 设置该gpio为输入
  162.     spin_unlock(&gpio_lock);
  163.     return 0;
  164. }
  165. EXPORT_SYMBOL(gpio_direction_input);

  166. /*
  167. 通过dir寄存器相应该gpio的位来设置gpio输入输出方向,为0,则设置成输出,为1,则设置出输入。
  168. 该函数是设置成输出,故设置dir寄存器为0.
  169. value参数用于选择gpio设置成输出后该gpio输出的值。
  170. */
  171. int gpio_direction_output(unsigned gpio, int value)
  172. {
  173.     struct gpio_controller *__iomem g = gpio2controller(gpio);
  174.     u32 temp;
  175.     u32 mask;
  176.     if (!g)
  177.         return -EINVAL;

  178.     spin_lock(&gpio_lock);
  179.     mask = __gpio_mask(gpio);
  180.     temp = __raw_readl(&g->dir);
  181.     temp &= ~mask; // 设置成0
  182.     //设置该gpio输出值
  183.     __raw_writel(mask, value ? &g->set_data : &g->clr_data);
  184.     __raw_writel(temp, &g->dir); // 设置gpio为输出
  185.     spin_unlock(&gpio_lock);
  186.     return 0;
  187. }
  188. EXPORT_SYMBOL(gpio_direction_output);

  189. /*
  190. 向gpio设置值,0或1。
  191. */
  192. void gpio_set_value(unsigned gpio, int value)
  193. {
  194.     if (__builtin_constant_p(value)) {
  195.         struct gpio_controller *__iomem g;
  196.         u32 mask;

  197.         if (gpio >= DAVINCI_N_GPIO)
  198.             __error_inval_gpio();

  199.         g = __gpio_to_controller(gpio);
  200.         mask = __gpio_mask(gpio);
  201.         if (value)
  202.             __raw_writel(mask, &g->set_data); // 该gpio输出高

  203.         else
  204.             __raw_writel(mask, &g->clr_data); // 该gpio输出低

  205.         return;
  206.     }

  207.     __gpio_set(gpio, value);
  208. }
  209. EXPORT_SYMBOL(gpio_set_value);

  210. /*
  211. 读取gpio的值,0或1.
  212. */
  213. int gpio_get_value(unsigned gpio)
  214. {
  215.     struct gpio_controller *__iomem g;

  216.     if (!__builtin_constant_p(gpio))/* 判断该gpio值是否为编译时常数,如果是常数,
  217.                                      函数返回 1,否则返回 0 */
  218.         return __gpio_get(gpio);

  219.     if (gpio >= DAVINCI_N_GPIO)
  220.         return __error_inval_gpio();

  221.     g = __gpio_to_controller(gpio);
  222.      
  223.     // 读取该gpio的值

  224.     return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
  225. }
  226. EXPORT_SYMBOL(gpio_get_value);

  227. /*
  228. * We expect irqs will normally be set up as input pins, but they can also be
  229. * used as output pins ... which is convenient for testing.
  230. *
  231. * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition
  232. * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have
  233. * a good way to hook those up ...
  234. *
  235. * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also
  236. * serve as EDMA event triggers.
  237. */

  238. /*
  239. 禁止相应该irq的gpio的中断。每个gpio都可以作为中断的来源,其中gpio0-gpio7是独立的中断来源,
  240. 也就是分配独立的中断号,其他gpio则共用5个GPIOBNK中断线。其优先级可以在board-evm.c
  241. 中设置(已经介绍过)。在dm644x平台上,中断是电平边缘触发的,禁止中断其实就是既不设置
  242. 上升沿触发,也不设置下降沿触发。
  243. */
  244. static void gpio_irq_disable(unsigned irq)
  245. {
  246.     struct gpio_controller *__iomem g = get_irq_chipdata(irq);
  247.     u32 mask = __gpio_mask(irq_to_gpio(irq));

  248.     __raw_writel(mask, &g->clr_falling); // 清除下降沿触发

  249.     __raw_writel(mask, &g->clr_rising); // 清除上升沿触发

  250. }

  251. /*
  252. 中断使能。
  253. 在dm644x平台上,中断是电平边缘触发的,其实就是设置为上升沿或下降沿中断。
  254. */
  255. static void gpio_irq_enable(unsigned irq)
  256. {
  257.     struct gpio_controller *__iomem g = get_irq_chipdata(irq);
  258.     u32 mask = __gpio_mask(irq_to_gpio(irq));

  259.     // 如果先前为下降沿中断,则使能为下降沿中断

  260.     if (irq_desc[irq].status & IRQT_FALLING)
  261.         __raw_writel(mask, &g->set_falling);
  262.      
  263.     // 如果先前为上升沿中断,则使能为上升沿中断

  264.     if (irq_desc[irq].status & IRQT_RISING)
  265.         __raw_writel(mask, &g->set_rising);
  266. }

  267. /*
  268. 设置中断类型。
  269. 在dm644x平台上,中断有上升沿和下降沿两种触发方式。
  270. */
  271. static int gpio_irq_type(unsigned irq, unsigned trigger)
  272. {
  273.     struct gpio_controller *__iomem g = get_irq_chipdata(irq);
  274.     u32 mask = __gpio_mask(irq_to_gpio(irq));

  275.     if (trigger & ~(IRQT_FALLING | IRQT_RISING))
  276.         return -EINVAL;

  277.     irq_desc[irq].status &= ~IRQT_BOTHEDGE;
  278.     irq_desc[irq].status |= trigger;

  279.     __raw_writel(mask, (trigger & IRQT_FALLING)
  280.          ? &g->set_falling : &g->clr_falling); // 设置为下降沿触发

  281.     __raw_writel(mask, (trigger & IRQT_RISING)
  282.          ? &g->set_rising : &g->clr_rising); // 设置为上升沿触发

  283.     return 0;
  284. }

  285. /*
  286. 该结构体用于注册到所有irq的中断描述结构体中(struct irqdesc),
  287. 而所有中断描述结构体定义成一个全局数组irq_desc 。
  288. */
  289. static struct irqchip gpio_irqchip = {
  290.     .unmask = gpio_irq_enable, /* 用于使能中断,
  291.                                      在enable_irq()等内核函数中会用到。*/
  292.     .mask = gpio_irq_disable,/* 用于禁止中断,
  293.                                      在disable_irq()等内核函数中会用到。*/
  294.     .type = gpio_irq_type, /* 用于设置中断类型,
  295.                                      在set_irq_type()内核函数中会用到。*/
  296. };

  297. /*
  298. 该函数将在下面的davinci_gpio_irq_setup中使用,将被注册到五个gpio bank中断的
  299. irq_desc结构中,目的是处理所有级联的gpio中断。所谓级联的中断, 就是指有n个中断
  300. 共用同一个中断线。
  301. 在dm644x平台中,除了gpio0-gpio7外,其他63个gpio都共用五个gpiobank中断线,在这里,
  302. gpio0-gpio7也被注册到gpiobank中断线,但实际上并不会使用,因为它们拥有自己的
  303. 中断线。其中,gpio0-gpio15共用IRQ_GPIOBNK0(56)中断线,gpio16-gpio31共用
  304. IRQ_GPIOBNK1(57)中断线,gpio32-gpio47共用IRQ_GPIOBNK2(58)中断线,
  305. gpio48-gpio63共用IRQ_GPIOBNK4(59)中断线,gpio64-gpio70共用
  306. IRQ_GPIOBNK5(60)中断线,
  307. 因为寄存器是32位的,所以实际上只有三组寄存器,第一组包含bank0和bank1,
  308. 也就是gpio0-gpio31,第二组包含bank2和bank3,也就是gpio32-gpio63,
  309. 第三组包含bank4和bank5,也就是gpio64-gpio70,剩余了25个位没有使用。
  310. */
  311. static void
  312. gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs)
  313. {
  314.     struct gpio_controller *__iomem g = get_irq_chipdata(irq);
  315.     u32 mask = 0xffff;

  316.     /* we only care about one bank */
  317.     // 如果bank中断线是寄数,则说明该中断的中断状态位在INTSTATn寄存器的高16位

  318.     if (irq & 1)
  319.         mask <<= 16;

  320.     /* temporarily mask (level sensitive) parent IRQ */
  321.     desc->chip->ack(irq);// 该ack函数会在arch/arm/mach-davinci/irq.c中注册。

  322.     while (1) {
  323.         u32 status;
  324.         struct irqdesc *gpio;
  325.         int n;
  326.         int res;

  327.         /* ack any irqs */
  328.         /*gpio中断发生后,硬件会在INTSTATn寄存器中置位相应位,
  329.          以备程序查询,确定是哪个gpio*/
  330.         status = __raw_readl(&g->intstat) & mask;
  331.         if (!status)
  332.             break;
  333.         __raw_writel(status, &g->intstat); // 向该位写1清除

  334.         if (irq & 1)
  335.             status >>= 16;

  336.         /* now demux them to the right lowlevel handler */
  337.         // 从下面的davinci_gpio_irq_setup函数可以看出来以下程序的运作。

  338.         n = (int)get_irq_data(irq); // 获取该bank对应的第一个gpio号

  339.         gpio = &irq_desc[n]; // 获取该bank第一个gpio号对应的中断描述符

  340.         while (status) { // 该bank可能有多个gpio发生了中断

  341.             res = ffs(status); // 获取第一个发生了中断的位(1-32)

  342.             n += res; /* 获得该gpio的中断线(系统实际上只有64(0-63)个中断线,
  343.                         但那些共用的gpio的中断也有自己的断描述符和中断线(从64开始),
  344.                         仅仅是为了管理,不能通过request_irq()函数来申请。*/
  345.             gpio += res; // 获得该gpio的中断描述符

  346.              
  347.             /* 调用下面注册的do_simple_IRQ例程
  348.              其又会调用用户通过request_irq()
  349.              注册的中断例程
  350.             */
  351.             desc_handle_irq(n - 1, gpio - 1, regs);
  352.             status >>= res;
  353.         }
  354.     }
  355.     desc->chip->unmask(irq); // 打开该irq中断线

  356.     /* now it may re-trigger */
  357. }

  358. /*
  359. * NOTE: for suspend/resume, probably best to make a sysdev (and class)
  360. * with its suspend/resume calls hooking into the results of the set_wake()
  361. * calls ... so if no gpios are wakeup events the clock can be disabled,
  362. * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
  363. * can be set appropriately for GPIOV33 pins.
  364. */
  365. /*
  366. 注册gpio中断例程到内核中,并初始化了一些寄存器。
  367. 该函数将会被board_evm.c(其浅析已经发表)中的evm_init()函数调用。具体调用过程如下:
  368. start_kernel()-->setup_arch()-->init_machine = mdesc->init_machine
  369. (init_machine是个全局函数指针变量,其指向的就是已经注册到机器描述符里evm_init())
  370. 调用函数指针init_machine()的例程是customize_machine(),其定义为
  371. arch_initcall(customize_machine),所以,接下来的调用过程是:
  372. start_kernel()-->do_basic_setup()-->do_initcalls()-->customize_machine()-->
  373. init_machine()(也就是evm_init()-->davinci_gpio_irq_setup。
  374. 从上可以看出经历了两个过程,才调用davinci_gpio_irq_setup例程来初始化gpio中断。
  375. */
  376. int __init davinci_gpio_irq_setup(void)
  377. {
  378.     unsigned gpio, irq, bank, banks;
  379.     struct clk *clk;

  380.     clk = clk_get(NULL, "gpio"); // 获取时钟

  381.     if (IS_ERR(clk)) {
  382.         printk(KERN_ERR "Error %ld getting gpio clock?\n",
  383.          PTR_ERR(clk));
  384.         return 0;
  385.     }

  386.     clk_enable(clk); // 使能gpio时钟并打开该模块电源


  387.     for (gpio = 0, irq = gpio_to_irq(0), bank = (cpu_is_davinci_dm355() ?
  388.      IRQ_DM355_GPIOBNK0 : (cpu_is_davinci_dm6467() ?
  389.      IRQ_DM646X_GPIOBNK0 : IRQ_GPIOBNK0)); // dm644x的IRQ_GPIOBNK0(56)

  390.      gpio < DAVINCI_N_GPIO; bank++) { // dm644x的DAVINCI_N_GPIO(71)

  391.         struct gpio_controller *__iomem g = gpio2controller(gpio);
  392.         unsigned i;

  393.         // 关该bank所有gpio的中断

  394.         __raw_writel(~0, &g->clr_falling);
  395.         __raw_writel(~0, &g->clr_rising);

  396.         /* set up all irqs in this bank */
  397.         // 同一个bank的所有gpio共用一个中断例程gpio_irq_handler

  398.         set_irq_chained_handler(bank, gpio_irq_handler);
  399.         set_irq_chipdata(bank, g);
  400.         set_irq_data(bank, (void *)irq);

  401.         for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;
  402.          i++, irq++, gpio++) {
  403.             set_irq_chip(irq, &gpio_irqchip); /* 注册用于gpio中断禁止、设能
  404.                                                  和类型选择的回调例程 */
  405.             set_irq_chipdata(irq, g); // 保存控制结构体(寄存器)的地址

  406.             set_irq_handler(irq, do_simple_IRQ);/* 为每个gpio中断设置同一个中
  407.                                                     断例程do_simple_IRQ*/
  408.             set_irq_flags(irq, IRQF_VALID); // fiq中断有效

  409.         }
  410.     }
  411. /*
  412. 一个共用bank中断线的gpio中断发生后的大致的流程是:
  413. --> gpio_irq_handler --> do_simple_IRQ --> __do_irq -->
  414. action->handler(用户使用request_irq()注册的中断例程)
  415. */
  416.     /* BINTEN -- per-bank interrupt enable. genirq would also let these
  417.      * bits be set/cleared dynamically.
  418.      */
  419.     if (cpu_is_davinci_dm355())
  420.         banks = 0x3f;
  421.     else
  422.         banks = 0x1f;
  423.      
  424.     // 向BINTEN寄存器写入0x1f(共5个位,每个位控制1个bank),打开所有的bank中断

  425.     __raw_writel(banks, (void *__iomem)
  426.          IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));

  427.     printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));

  428.     return 0;
  429. }

  430.  


  431. gpio.h


  432. /*
  433. * TI DaVinci GPIO Support
  434. *
  435. * Copyright (c) 2006 David Brownell
  436. * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
  437. *
  438. * This program is free software; you can redistribute it and/or modify
  439. * it under the terms of the GNU General Public License as published by
  440. * the Free Software Foundation; either version 2 of the License, or
  441. * (at your option) any later version.
  442. */

  443. #ifndef __DAVINCI_GPIO_H
  444. #define __DAVINCI_GPIO_H

  445. /*
  446. * basic gpio routines
  447. *
  448. * board-specific init should be done by arch/.../.../board-XXX.c (maybe
  449. * initializing banks together) rather than boot loaders; kexec() won't
  450. * go through boot loaders.
  451. *
  452. * the gpio clock will be turned on when gpios are used, and you may also
  453. * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are
  454. * used as gpios, not with other peripherals.
  455. *
  456. * GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, and maybe
  457. * for later updates, code should write GPIO(N) or:
  458. * - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53)
  459. * - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70)
  460. *
  461. * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc
  462. * for now, that's != GPIO(N)
  463. */
  464. #define GPIO(X) (X) /* 0 <= X <= 70 */
  465. #define GPIOV18(X) (X) /* 1.8V i/o; 0 <= X <= 53 */
  466. #define GPIOV33(X) ((X)+54) /* 3.3V i/o; 0 <= X <= 17 */

  467. /*
  468. 寄存器都是32位到,每位对应一个gpio。
  469. */
  470. struct gpio_controller {
  471.     u32 dir; // gpio方向设置寄存器

  472.     u32 out_data; // gpio设置为输出时,表示输出状态(0或1)

  473.     u32 set_data; // gpio设置为输出时,用于输出高电平

  474.     u32 clr_data; // gpio设置为输出时,用于输出低电平

  475.     u32 in_data; // gpio设置为输入时,用于读取输入值

  476.     u32 set_rising; // gpio中断上升沿触发设置

  477.     u32 clr_rising; // gpio中断上升沿触发清除

  478.     u32 set_falling; // gpio中断下降沿触发设置

  479.     u32 clr_falling; // gpio中断下降沿触发清除

  480.     u32 intstat; // gpio中断状态位,由硬件设置,可读取,写1时清除。

  481. };

  482. /* The __gpio_to_controller() and __gpio_mask() functions inline to constants
  483. * with constant parameters; or in outlined code they execute at runtime.
  484. *
  485. * You'd access the controller directly when reading or writing more than
  486. * one gpio value at a time, and to support wired logic where the value
  487. * being driven by the cpu need not match the value read back.
  488. *
  489. * These are NOT part of the cross-platform GPIO interface
  490. */
  491. static inline struct gpio_controller *__iomem
  492. __gpio_to_controller(unsigned gpio)
  493. {
  494.     void *__iomem ptr;

  495.     if (gpio >= DAVINCI_N_GPIO)
  496.         return NULL;

  497.     if (gpio < 32)
  498.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
  499.     else if (gpio < 64)
  500.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
  501.     else if (gpio < 96)
  502.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
  503.     else
  504.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x88);

  505.     return ptr;
  506. }

  507. static inline u32 __gpio_mask(unsigned gpio)
  508. {
  509.     return 1 << (gpio % 32);
  510. }

  511. /* The get/set/clear functions will inline when called with constant
  512. * parameters, for low-overhead bitbanging. Illegal constant parameters
  513. * cause link-time errors.
  514. *
  515. * Otherwise, calls with variable parameters use outlined functions.
  516. */
  517. extern int __error_inval_gpio(void);

  518. extern void __gpio_set(unsigned gpio, int value);
  519. extern int __gpio_get(unsigned gpio);

  520. /* Returns zero or nonzero; works for gpios configured as inputs OR
  521. * as outputs.
  522. *
  523. * NOTE: changes in reported values are synchronized to the GPIO clock.
  524. * This is most easily seen after calling gpio_set_value() and then immediatly
  525. * gpio_get_value(), where the gpio_get_value() would return the old value
  526. * until the GPIO clock ticks and the new value gets latched.
  527. */
  528. extern int gpio_get_value(unsigned gpio);
  529. extern void gpio_set_value(unsigned gpio, int value);


  530. /* powerup default direction is IN */
  531. extern int gpio_direction_input(unsigned gpio);
  532. extern int gpio_direction_output(unsigned gpio, int value);

  533. #include <asm-generic/gpio.h> /* cansleep wrappers */

  534. extern int gpio_request(unsigned gpio, const char *tag);
  535. extern void gpio_free(unsigned gpio);

  536. static inline int gpio_to_irq(unsigned gpio)
  537. {
  538.     return DAVINCI_N_AINTC_IRQ + gpio;
  539. }

  540. static inline int irq_to_gpio(unsigned irq)
  541. {
  542.     return irq - DAVINCI_N_AINTC_IRQ;
  543. }

  544. #endif /* __DAVINCI_GPIO_H */

阅读(1513) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~