gpio_request()函数

其原型为 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.     
  13. #include <linux/errno.h>       
  14. #include <linux/kernel.h>       
  15. #include <linux/list.h>       
  16. #include <linux/module.h>       
  17. #include <linux/err.h>       
  18. #include <linux/bitops.h>       
  19.     
  20. #include <asm/irq.h>       
  21. #include <asm/io.h>       
  22. #include <asm/hardware/clock.h>       
  23.     
  24. #include <asm/arch/irqs.h>       
  25. #include <asm/arch/hardware.h>       
  26. #include <asm/arch/gpio.h>       
  27. #include <asm/arch/cpu.h>       
  28.     
  29. #include <asm/mach/irq.h>       
  30.     
  31. /*    
  32. 该文件实现了gpio的各种应用功能和向内核注册gpio的中断例程等功能。   
  33. 用户的驱动程序可调用gpio_request和gpio_free使用或释放该gpio,   
  34. 可以调用gpio_direction_input和gpio_direction_output函数设置gpio输入输出方向,   
  35. 调用gpio_get_value和gpio_set_value获取设置值。   
  36. */     
  37.     
  38. static DEFINE_SPINLOCK(gpio_lock);     
  39.     
  40. /* 总共有DAVINCI_N_GPIO(71)个gpio引脚,故使用相应多的bit来记录这些引脚的使用状态 */     
  41. static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);     
  42.     
  43. /*   
  44. 申请一个gpio,其实就是检查该gpio是否空闲,如果空闲就可以使用并将该gpio相应的bit置位   
  45. (在gpio_in_use中)。   
  46. */     
  47. int gpio_request(unsigned gpio, const char *tag)     
  48. {     
  49.     if (gpio >= DAVINCI_N_GPIO)     
  50.         return -EINVAL;     
  51.     if (test_and_set_bit(gpio, gpio_in_use))     
  52.         return -EBUSY;     
  53.     return 0;     
  54. }     
  55. EXPORT_SYMBOL(gpio_request);     
  56.     
  57. /*   
  58. 释放一个gpio,其实就是清除gpio相应的控制bit位(在gpio_in_use中)。   
  59. */     
  60. void gpio_free(unsigned gpio)     
  61. {     
  62.     if (gpio >= DAVINCI_N_GPIO)     
  63.         return;     
  64.     clear_bit(gpio, gpio_in_use);     
  65. }     
  66. EXPORT_SYMBOL(gpio_free);     
  67.     
  68. /* 获得gpio_controller结构体指针,gpio_controller结构体是gpio的核心控制单元,里面包含   
  69. gpio的设置和数据寄存器。该结构体和__gpio_to_controller函数在/include/asm-arm/   
  70. arch-davinci/gpio.h中定义,具体如下:   
  71. struct gpio_controller {   
  72.     u32    dir;   
  73.     u32    out_data;   
  74.     u32    set_data;   
  75.     u32    clr_data;   
  76.     u32    in_data;   
  77.     u32    set_rising;   
  78.     u32    clr_rising;   
  79.     u32    set_falling;   
  80.     u32    clr_falling;   
  81.     u32    intstat;   
  82. };   
  83.   
  84. static inline struct gpio_controller *__iomem   
  85. __gpio_to_controller(unsigned gpio)   
  86. {   
  87.     void *__iomem ptr;   
  88.     if (gpio >= DAVINCI_N_GPIO)   
  89.         return NULL;   
  90.   
  91.     if (gpio < 32)   
  92.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);   
  93.     else if (gpio < 64)   
  94.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);   
  95.     else if (gpio < 96)   
  96.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);   
  97.     else   
  98.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x88);   
  99.     return ptr;   
  100. }   
  101. 由上面的定义和ti的SPRUE25.pdf手册可以看出,__gpio_to_controller函数返回的是   
  102. gpio_controller结构体到第一个成员dir的虚拟地址。获取了这个结构体指针后,   
  103. 便可以控制相应的gpio了。dm644x共有71个gpio,   
  104. 所以使用三个gpio_controller结构体控制,关于这个后面会由更详细的分析,   
  105. */     
  106. /* create a non-inlined version */     
  107. static struct gpio_controller *__iomem gpio2controller(unsigned gpio)     
  108. {     
  109.     return __gpio_to_controller(gpio);     
  110. }     
  111.     
  112. /*    
  113. 向某个gpio设置值,0或1。如果向gpio写1,则向set_data寄存器相应的位置1,如果写0,   
  114. 则向clr_data寄存器相应的位置1.__gpio_mask函数在gpio.h中定义,定义如下,   
  115. static inline u32 __gpio_mask(unsigned gpio)   
  116. {   
  117.     return 1 << (gpio % 32);   
  118. }   
  119. 因为71个引脚由3个结构体控制,第一个控制前32个gpio,第二个控制次32个gpio,   
  120. 最后一个控制剩余的7个gpio,故__gpio_mask函数的作用是找到在其相应控制结构体里的偏移数,   
  121. 比如gpio34,那么其由第二个结构体控制,在这个机构体里的偏移是3(从0开始算,就是第二位)。   
  122. 使用这个函数之前,必须确认该gpio设置成输出模式。   
  123. */     
  124. /*   
  125. * Assuming the pin is muxed as a gpio output, set its output value.   
  126. */     
  127. void __gpio_set(unsigned gpio, int value)     
  128. {     
  129.     struct gpio_controller *__iomem g = gpio2controller(gpio);     
  130.     // 设置gpio的值       
  131.     __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);      
  132. }     
  133. EXPORT_SYMBOL(__gpio_set);     
  134.     
  135. /*    
  136. 通过读取in_data寄存器相应该gpio的位来读取gpio的值。   
  137. 使用这个函数之前,必须确认该gpio设置成输入模式,否则获得到值不可预料。    
  138. */     
  139. /*   
  140. * Read the pin's value (works even if it's set up as output);   
  141. * returns zero/nonzero.   
  142. *   
  143. * Note that changes are synched to the GPIO clock, so reading values back   
  144. * right after you've set them may give old values.   
  145. */     
  146. int __gpio_get(unsigned gpio)     
  147. {     
  148.     struct gpio_controller *__iomem g = gpio2controller(gpio);     
  149.     /* 读取gpio的值,!!的目的是使得返回的值为0或1.*/     
  150.     return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));         
  151. }                                                                                                                  }     
  152. EXPORT_SYMBOL(__gpio_get);     
  153.     
  154. /*    
  155. 通过dir寄存器相应该gpio的位来设置gpio输入输出方向,为0,则设置成输出,为1,则设置出输入。   
  156. 该函数是设置成输入,故设置dir寄存器为1.   
  157.  正如应为所说的,必须确认该引脚是作为gpio功能,而不是某个模块到功能,比如spi。通过PINMUX0   
  158. 和PINMUX1两个寄存器来设置。   
  159. */     
  160. /*--------------------------------------------------------------------------*/     
  161.     
  162. /*   
  163. * board setup code *MUST* set PINMUX0 and PINMUX1 as   
  164. * needed, and enable the GPIO clock.   
  165. */     
  166. int gpio_direction_input(unsigned gpio)     
  167. {     
  168.     struct gpio_controller *__iomem g = gpio2controller(gpio);     
  169.     u32 temp;     
  170.     u32 mask;     
  171.     
  172.     if (!g)     
  173.         return -EINVAL;     
  174.     spin_lock(&gpio_lock);     
  175.     mask = __gpio_mask(gpio);     
  176.     temp = __raw_readl(&g->dir);     
  177.     temp |= mask;    // 设置成1       
  178.     __raw_writel(temp, &g->dir);    // 设置该gpio为输入       
  179.     spin_unlock(&gpio_lock);     
  180.     return 0;     
  181. }     
  182. EXPORT_SYMBOL(gpio_direction_input);     
  183.     
  184. /*   
  185. 通过dir寄存器相应该gpio的位来设置gpio输入输出方向,为0,则设置成输出,为1,则设置出输入。   
  186. 该函数是设置成输出,故设置dir寄存器为0.   
  187. value参数用于选择gpio设置成输出后该gpio输出的值。   
  188. */     
  189. int gpio_direction_output(unsigned gpio, int value)     
  190. {     
  191.     struct gpio_controller *__iomem g = gpio2controller(gpio);     
  192.     u32 temp;     
  193.     u32 mask;     
  194.     if (!g)     
  195.         return -EINVAL;     
  196.     
  197.     spin_lock(&gpio_lock);     
  198.     mask = __gpio_mask(gpio);     
  199.     temp = __raw_readl(&g->dir);     
  200.     temp &= ~mask;    // 设置成0        
  201.     //设置该gpio输出值       
  202.     __raw_writel(mask, value ? &g->set_data : &g->clr_data);     
  203.     __raw_writel(temp, &g->dir);    // 设置gpio为输出       
  204.     spin_unlock(&gpio_lock);     
  205.     return 0;     
  206. }     
  207. EXPORT_SYMBOL(gpio_direction_output);     
  208.     
  209. /*   
  210. 向gpio设置值,0或1。   
  211. */     
  212. void gpio_set_value(unsigned gpio, int value)     
  213. {     
  214.     if (__builtin_constant_p(value)) {     
  215.         struct gpio_controller *__iomem g;     
  216.         u32 mask;     
  217.     
  218.         if (gpio >= DAVINCI_N_GPIO)     
  219.             __error_inval_gpio();     
  220.     
  221.         g = __gpio_to_controller(gpio);     
  222.         mask = __gpio_mask(gpio);     
  223.         if (value)     
  224.             __raw_writel(mask, &g->set_data);    // 该gpio输出高       
  225.     
  226.         else     
  227.             __raw_writel(mask, &g->clr_data);    // 该gpio输出低       
  228.     
  229.         return;     
  230.     }     
  231.     
  232.     __gpio_set(gpio, value);     
  233. }     
  234. EXPORT_SYMBOL(gpio_set_value);     
  235.     
  236. /*   
  237. 读取gpio的值,0或1.   
  238. */     
  239. int gpio_get_value(unsigned gpio)     
  240. {     
  241.     struct gpio_controller *__iomem g;     
  242.     
  243.     if (!__builtin_constant_p(gpio))/* 判断该gpio值是否为编译时常数,如果是常数,   
  244.                                      函数返回 1,否则返回 0 */     
  245.         return __gpio_get(gpio);     
  246.     
  247.     if (gpio >= DAVINCI_N_GPIO)     
  248.         return __error_inval_gpio();     
  249.     
  250.     g = __gpio_to_controller(gpio);     
  251.          
  252.     // 读取该gpio的值       
  253.     
  254.     return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));     
  255. }     
  256. EXPORT_SYMBOL(gpio_get_value);     
  257.     
  258. /*   
  259. * We expect irqs will normally be set up as input pins, but they can also be   
  260. * used as output pins ... which is convenient for testing.   
  261. *   
  262. * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition   
  263. * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have   
  264. * a good way to hook those up ...   
  265. *   
  266. * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also   
  267. * serve as EDMA event triggers.   
  268. */     
  269.     
  270. /*   
  271. 禁止相应该irq的gpio的中断。每个gpio都可以作为中断的来源,其中gpio0-gpio7是独立的中断来源,   
  272. 也就是分配独立的中断号,其他gpio则共用5个GPIOBNK中断线。其优先级可以在board-evm.c   
  273. 中设置(已经介绍过)。在dm644x平台上,中断是电平边缘触发的,禁止中断其实就是既不设置   
  274. 上升沿触发,也不设置下降沿触发。   
  275. */     
  276. static void gpio_irq_disable(unsigned irq)     
  277. {     
  278.     struct gpio_controller *__iomem g = get_irq_chipdata(irq);     
  279.     u32 mask = __gpio_mask(irq_to_gpio(irq));     
  280.     
  281.     __raw_writel(mask, &g->clr_falling);    // 清除下降沿触发       
  282.     
  283.     __raw_writel(mask, &g->clr_rising);        // 清除上升沿触发       
  284.     
  285. }     
  286.     
  287. /*   
  288. 中断使能。   
  289. 在dm644x平台上,中断是电平边缘触发的,其实就是设置为上升沿或下降沿中断。   
  290. */     
  291. static void gpio_irq_enable(unsigned irq)     
  292. {     
  293.     struct gpio_controller *__iomem g = get_irq_chipdata(irq);     
  294.     u32 mask = __gpio_mask(irq_to_gpio(irq));     
  295.     
  296.     // 如果先前为下降沿中断,则使能为下降沿中断       
  297.     
  298.     if (irq_desc[irq].status & IRQT_FALLING)     
  299.         __raw_writel(mask, &g->set_falling);     
  300.          
  301.     // 如果先前为上升沿中断,则使能为上升沿中断       
  302.     
  303.     if (irq_desc[irq].status & IRQT_RISING)         
  304.         __raw_writel(mask, &g->set_rising);     
  305. }     
  306.     
  307. /*   
  308. 设置中断类型。   
  309. 在dm644x平台上,中断有上升沿和下降沿两种触发方式。   
  310. */     
  311. static int gpio_irq_type(unsigned irq, unsigned trigger)     
  312. {     
  313.     struct gpio_controller *__iomem g = get_irq_chipdata(irq);     
  314.     u32 mask = __gpio_mask(irq_to_gpio(irq));     
  315.     
  316.     if (trigger & ~(IRQT_FALLING | IRQT_RISING))     
  317.         return -EINVAL;     
  318.     
  319.     irq_desc[irq].status &= ~IRQT_BOTHEDGE;     
  320.     irq_desc[irq].status |= trigger;     
  321.     
  322.     __raw_writel(mask, (trigger & IRQT_FALLING)     
  323.          ? &g->set_falling : &g->clr_falling);     // 设置为下降沿触发       
  324.     
  325.     __raw_writel(mask, (trigger & IRQT_RISING)     
  326.          ? &g->set_rising : &g->clr_rising);    // 设置为上升沿触发       
  327.     
  328.     return 0;     
  329. }     
  330.     
  331. /*    
  332. 该结构体用于注册到所有irq的中断描述结构体中(struct irqdesc),   
  333. 而所有中断描述结构体定义成一个全局数组irq_desc 。   
  334. */     
  335. static struct irqchip gpio_irqchip = {     
  336.     .unmask        = gpio_irq_enable, /* 用于使能中断,   
  337.                                      在enable_irq()等内核函数中会用到。*/         
  338.     .mask        = gpio_irq_disable,/* 用于禁止中断,   
  339.                                      在disable_irq()等内核函数中会用到。*/     
  340.     .type        = gpio_irq_type, /* 用于设置中断类型,   
  341.                                      在set_irq_type()内核函数中会用到。*/     
  342. };     
  343.     
  344. /*   
  345. 该函数将在下面的davinci_gpio_irq_setup中使用,将被注册到五个gpio bank中断的   
  346. irq_desc结构中,目的是处理所有级联的gpio中断。所谓级联的中断, 就是指有n个中断   
  347. 共用同一个中断线。   
  348. 在dm644x平台中,除了gpio0-gpio7外,其他63个gpio都共用五个gpiobank中断线,在这里,   
  349. gpio0-gpio7也被注册到gpiobank中断线,但实际上并不会使用,因为它们拥有自己的   
  350. 中断线。其中,gpio0-gpio15共用IRQ_GPIOBNK0(56)中断线,gpio16-gpio31共用   
  351. IRQ_GPIOBNK1(57)中断线,gpio32-gpio47共用IRQ_GPIOBNK2(58)中断线,   
  352. gpio48-gpio63共用IRQ_GPIOBNK4(59)中断线,gpio64-gpio70共用   
  353. IRQ_GPIOBNK5(60)中断线,   
  354. 因为寄存器是32位的,所以实际上只有三组寄存器,第一组包含bank0和bank1,   
  355. 也就是gpio0-gpio31,第二组包含bank2和bank3,也就是gpio32-gpio63,   
  356. 第三组包含bank4和bank5,也就是gpio64-gpio70,剩余了25个位没有使用。   
  357. */     
  358. static void     
  359. gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs)     
  360. {     
  361.     struct gpio_controller *__iomem g = get_irq_chipdata(irq);     
  362.     u32 mask = 0xffff;     
  363.     
  364.     /* we only care about one bank */     
  365.     // 如果bank中断线是寄数,则说明该中断的中断状态位在INTSTATn寄存器的高16位       
  366.     
  367.     if (irq & 1)     
  368.         mask <<= 16;     
  369.     
  370.     /* temporarily mask (level sensitive) parent IRQ */     
  371.     desc->chip->ack(irq);// 该ack函数会在arch/arm/mach-davinci/irq.c中注册。       
  372.     
  373.     while (1) {     
  374.         u32        status;     
  375.         struct irqdesc    *gpio;     
  376.         int        n;     
  377.         int        res;     
  378.     
  379.         /* ack any irqs */     
  380.         /*gpio中断发生后,硬件会在INTSTATn寄存器中置位相应位,   
  381.          以备程序查询,确定是哪个gpio*/     
  382.         status = __raw_readl(&g->intstat) & mask;      
  383.         if (!status)     
  384.             break;     
  385.         __raw_writel(status, &g->intstat);    // 向该位写1清除       
  386.     
  387.         if (irq & 1)     
  388.             status >>= 16;     
  389.     
  390.         /* now demux them to the right lowlevel handler */     
  391.         // 从下面的davinci_gpio_irq_setup函数可以看出来以下程序的运作。       
  392.     
  393.         n = (int)get_irq_data(irq);    // 获取该bank对应的第一个gpio号       
  394.     
  395.         gpio = &irq_desc[n];    // 获取该bank第一个gpio号对应的中断描述符       
  396.     
  397.         while (status) {    // 该bank可能有多个gpio发生了中断       
  398.     
  399.             res = ffs(status);    // 获取第一个发生了中断的位(1-32)       
  400.     
  401.             n += res;    /* 获得该gpio的中断线(系统实际上只有64(0-63)个中断线,   
  402.                         但那些共用的gpio的中断也有自己的断描述符和中断线(从64开始),   
  403.                         仅仅是为了管理,不能通过request_irq()函数来申请。*/     
  404.             gpio += res;    //     获得该gpio的中断描述符       
  405.     
  406.                  
  407.             /* 调用下面注册的do_simple_IRQ例程   
  408.              其又会调用用户通过request_irq()   
  409.              注册的中断例程   
  410.             */     
  411.             desc_handle_irq(n - 1, gpio - 1, regs);         
  412.             status >>= res;             
  413.         }     
  414.     }     
  415.     desc->chip->unmask(irq);    // 打开该irq中断线       
  416.     
  417.     /* now it may re-trigger */     
  418. }     
  419.     
  420. /*   
  421. * NOTE: for suspend/resume, probably best to make a sysdev (and class)   
  422. * with its suspend/resume calls hooking into the results of the set_wake()   
  423. * calls ... so if no gpios are wakeup events the clock can be disabled,   
  424. * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0   
  425. * can be set appropriately for GPIOV33 pins.   
  426. */     
  427. /*   
  428. 注册gpio中断例程到内核中,并初始化了一些寄存器。   
  429. 该函数将会被board_evm.c(其浅析已经发表)中的evm_init()函数调用。具体调用过程如下:   
  430. start_kernel()-->setup_arch()-->init_machine = mdesc->init_machine   
  431. (init_machine是个全局函数指针变量,其指向的就是已经注册到机器描述符里evm_init());   
  432. 调用函数指针init_machine()的例程是customize_machine(),其定义为   
  433. arch_initcall(customize_machine),所以,接下来的调用过程是:   
  434. start_kernel()-->do_basic_setup()-->do_initcalls()-->customize_machine()-->   
  435. init_machine()(也就是evm_init())-->davinci_gpio_irq_setup。   
  436. 从上可以看出经历了两个过程,才调用davinci_gpio_irq_setup例程来初始化gpio中断。   
  437. */     
  438. int __init davinci_gpio_irq_setup(void)     
  439. {     
  440.     unsigned    gpio, irq, bank, banks;     
  441.     struct clk    *clk;     
  442.     
  443.     clk = clk_get(NULL, "gpio");    // 获取时钟       
  444.     
  445.     if (IS_ERR(clk)) {     
  446.         printk(KERN_ERR "Error %ld getting gpio clock?\n",     
  447.          PTR_ERR(clk));     
  448.         return 0;     
  449.     }     
  450.     
  451.     clk_enable(clk);    // 使能gpio时钟并打开该模块电源       
  452.     
  453.     
  454.     for (gpio = 0, irq = gpio_to_irq(0), bank = (cpu_is_davinci_dm355() ?     
  455.      IRQ_DM355_GPIOBNK0 : (cpu_is_davinci_dm6467() ?     
  456.      IRQ_DM646X_GPIOBNK0 : IRQ_GPIOBNK0));    // dm644x的IRQ_GPIOBNK0(56)       
  457.     
  458.      gpio < DAVINCI_N_GPIO; bank++) {    // dm644x的DAVINCI_N_GPIO(71)       
  459.     
  460.         struct gpio_controller    *__iomem g = gpio2controller(gpio);     
  461.         unsigned        i;     
  462.     
  463.         // 关该bank所有gpio的中断       
  464.     
  465.         __raw_writel(~0, &g->clr_falling);     
  466.         __raw_writel(~0, &g->clr_rising);     
  467.     
  468.         /* set up all irqs in this bank */     
  469.         // 同一个bank的所有gpio共用一个中断例程gpio_irq_handler       
  470.     
  471.         set_irq_chained_handler(bank, gpio_irq_handler);     
  472.         set_irq_chipdata(bank, g);     
  473.         set_irq_data(bank, (void *)irq);     
  474.     
  475.         for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;     
  476.          i++, irq++, gpio++) {     
  477.             set_irq_chip(irq, &gpio_irqchip);    /* 注册用于gpio中断禁止、设能   
  478.                                                  和类型选择的回调例程 */     
  479.             set_irq_chipdata(irq, g);            // 保存控制结构体(寄存器)的地址       
  480.     
  481.             set_irq_handler(irq, do_simple_IRQ);/* 为每个gpio中断设置同一个中   
  482.                                                     断例程do_simple_IRQ*/     
  483.             set_irq_flags(irq, IRQF_VALID);        // fiq中断有效       
  484.     
  485.         }     
  486.     }     
  487. /*       
  488. 一个共用bank中断线的gpio中断发生后的大致的流程是:   
  489. --> gpio_irq_handler --> do_simple_IRQ --> __do_irq -->    
  490. action->handler(用户使用request_irq()注册的中断例程)   
  491. */     
  492.     /* BINTEN -- per-bank interrupt enable. genirq would also let these   
  493.      * bits be set/cleared dynamically.   
  494.      */     
  495.     if (cpu_is_davinci_dm355())     
  496.         banks = 0x3f;     
  497.     else     
  498.         banks = 0x1f;     
  499.          
  500.     // 向BINTEN寄存器写入0x1f(共5个位,每个位控制1个bank),打开所有的bank中断       
  501.     
  502.     __raw_writel(banks, (void *__iomem)     
  503.          IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));     
  504.     
  505.     printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));     
  506.     
  507.     return 0;     
  508. }     
  509.     
  510.      
  511.     
  512.     
  513. gpio.h     
  514.     
  515.     
  516. /*   
  517. * TI DaVinci GPIO Support   
  518. *   
  519. * Copyright (c) 2006 David Brownell   
  520. * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>   
  521. *   
  522. * This program is free software; you can redistribute it and/or modify   
  523. * it under the terms of the GNU General Public License as published by   
  524. * the Free Software Foundation; either version 2 of the License, or   
  525. * (at your option) any later version.   
  526. */     
  527.     
  528. #ifndef    __DAVINCI_GPIO_H       
  529. #define    __DAVINCI_GPIO_H       
  530.     
  531. /*   
  532. * basic gpio routines   
  533. *   
  534. * board-specific init should be done by arch/.../.../board-XXX.c (maybe   
  535. * initializing banks together) rather than boot loaders; kexec() won't   
  536. * go through boot loaders.   
  537. *   
  538. * the gpio clock will be turned on when gpios are used, and you may also   
  539. * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are   
  540. * used as gpios, not with other peripherals.   
  541. *   
  542. * GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, and maybe   
  543. * for later updates, code should write GPIO(N) or:   
  544. * - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53)   
  545. * - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70)   
  546. *   
  547. * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc   
  548. * for now, that's != GPIO(N)   
  549. */     
  550. #define    GPIO(X)        (X)        /* 0 <= X <= 70 */       
  551. #define    GPIOV18(X)    (X)        /* 1.8V i/o; 0 <= X <= 53 */       
  552. #define    GPIOV33(X)    ((X)+54)    /* 3.3V i/o; 0 <= X <= 17 */       
  553.     
  554. /*    
  555. 寄存器都是32位到,每位对应一个gpio。   
  556. */     
  557. struct gpio_controller {     
  558.     u32    dir;            // gpio方向设置寄存器       
  559.     
  560.     u32    out_data;        // gpio设置为输出时,表示输出状态(0或1)       
  561.     
  562.     u32    set_data;        // gpio设置为输出时,用于输出高电平       
  563.     
  564.     u32    clr_data;        // gpio设置为输出时,用于输出低电平       
  565.     
  566.     u32    in_data;        // gpio设置为输入时,用于读取输入值       
  567.     
  568.     u32    set_rising;        // gpio中断上升沿触发设置       
  569.     
  570.     u32    clr_rising;        // gpio中断上升沿触发清除       
  571.     
  572.     u32    set_falling;    // gpio中断下降沿触发设置       
  573.     
  574.     u32    clr_falling;    // gpio中断下降沿触发清除       
  575.     
  576.     u32    intstat;        // gpio中断状态位,由硬件设置,可读取,写1时清除。       
  577.     
  578. };     
  579.     
  580. /* The __gpio_to_controller() and __gpio_mask() functions inline to constants   
  581. * with constant parameters; or in outlined code they execute at runtime.   
  582. *   
  583. * You'd access the controller directly when reading or writing more than   
  584. * one gpio value at a time, and to support wired logic where the value   
  585. * being driven by the cpu need not match the value read back.   
  586. *   
  587. * These are NOT part of the cross-platform GPIO interface   
  588. */     
  589. static inline struct gpio_controller *__iomem     
  590. __gpio_to_controller(unsigned gpio)     
  591. {     
  592.     void *__iomem ptr;     
  593.     
  594.     if (gpio >= DAVINCI_N_GPIO)     
  595.         return NULL;     
  596.     
  597.     if (gpio < 32)     
  598.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);     
  599.     else if (gpio < 64)     
  600.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);     
  601.     else if (gpio < 96)     
  602.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);     
  603.     else     
  604.         ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x88);     
  605.     
  606.     return ptr;     
  607. }     
  608.     
  609. static inline u32 __gpio_mask(unsigned gpio)     
  610. {     
  611.     return 1 << (gpio % 32);     
  612. }     
  613.     
  614. /* The get/set/clear functions will inline when called with constant   
  615. * parameters, for low-overhead bitbanging. Illegal constant parameters   
  616. * cause link-time errors.   
  617. *   
  618. * Otherwise, calls with variable parameters use outlined functions.   
  619. */     
  620. extern int __error_inval_gpio(void);     
  621.     
  622. extern void __gpio_set(unsigned gpio, int value);     
  623. extern int __gpio_get(unsigned gpio);     
  624.     
  625. /* Returns zero or nonzero; works for gpios configured as inputs OR   
  626. * as outputs.   
  627. *   
  628. * NOTE: changes in reported values are synchronized to the GPIO clock.   
  629. * This is most easily seen after calling gpio_set_value() and then immediatly   
  630. * gpio_get_value(), where the gpio_get_value() would return the old value   
  631. * until the GPIO clock ticks and the new value gets latched.   
  632. */     
  633. extern int gpio_get_value(unsigned gpio);     
  634. extern void gpio_set_value(unsigned gpio, int value);     
  635.     
  636.     
  637. /* powerup default direction is IN */     
  638. extern int gpio_direction_input(unsigned gpio);     
  639. extern int gpio_direction_output(unsigned gpio, int value);     
  640.     
  641. #include <asm-generic/gpio.h>    /* cansleep wrappers */       
  642.     
  643. extern int gpio_request(unsigned gpio, const char *tag);     
  644. extern void gpio_free(unsigned gpio);     
  645.     
  646. static inline int gpio_to_irq(unsigned gpio)     
  647. {     
  648.     return DAVINCI_N_AINTC_IRQ + gpio;     
  649. }     
  650.     
  651. static inline int irq_to_gpio(unsigned irq)     
  652. {     
  653.     return irq - DAVINCI_N_AINTC_IRQ;     
  654. }     
  655.     
  656. #endif                /* __DAVINCI_GPIO_H */ 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值