註冊中斷:對每一個pin進行循環遍歷for (pin_num = 0; pin_num < min_t(int, ZYNQ_GPIO_NR_GPIOS, (int)chip->ngpio); pin_num++)node
gpio_irq = irq_find_mapping(irq_domain, pin_num); 將GPIO號映射爲Linux系統中斷號。app
在Linux中斷系統中,一個irq_domain表示一箇中斷控制器,其內中斷由0開始編號(尚存在疑問)dom
unsigned int irq_find_mapping(struct irq_domain *domain, irq_hw_number_t hwirq)函數
將一箇中斷控制器上的某個硬件中斷映射爲某個Linux系統中斷。this
/** * struct irq_domain - Hardware interrupt number translation object * @link: Element in global irq_domain list. * @name: Name of interrupt domain * @ops: pointer to irq_domain methods * @host_data: private data pointer for use by owner. Not touched by irq_domain * core code. * * Optional elements * @of_node: Pointer to device tree nodes associated with the irq_domain. Used * when decoding device tree interrupt specifiers. * @gc: Pointer to a list of generic chips. There is a helper function for * setting up one or more generic chips for interrupt controllers * drivers using the generic chip library which uses this pointer. * * Revmap data, used internally by irq_domain * @revmap_direct_max_irq: The largest hwirq that can be set for controllers that * support direct mapping * @revmap_size: Size of the linear map table @linear_revmap[] * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map * @linear_revmap: Linear table of hwirq->virq reverse mappings */ struct irq_domain { struct list_head link; const char *name; const struct irq_domain_ops *ops; void *host_data; /* Optional data */ struct device_node *of_node; struct irq_domain_chip_generic *gc; /* reverse map data. The linear map gets appended to the irq_domain */ irq_hw_number_t hwirq_max; unsigned int revmap_direct_max_irq; unsigned int revmap_size; struct radix_tree_root revmap_tree; unsigned int linear_revmap[]; };
revmap_direct_max_irq: 小於該值的中斷,Linux中斷號和硬件中斷號相同,直接返回。spa
revmap_size: 線性反向映射(彷佛要求域內IRQ從零開始,有點矛盾),小於該值的hwirq直接利用linear_revmap作查找。code
不然用radix tree來查找映射。orm
irq_set_chip_and_handler(gpio_irq, &zynq_gpio_irqchip, handle_simple_irq);
ip
調用irq_get_desc_lock(irq, &flags, 0);,獲取irq對應的irq_desc。並設定irq_desc的chip:desc->irq_data.chip = chip;ci
調用irq_reserve_irq(irq);,將allocated_irqs中斷位圖中相應的中斷標識爲已佔用。
調用__irq_set_handler,將irq_desc中的handle_irq設定:desc->handle_irq = handle;
irq_set_chip_data(gpio_irq, (void *)gpio);
這個比較簡單,將要用私有的變量關聯到irq,desc->irq_data.chip_data = data;
set_irq_flags(gpio_irq, IRQF_VALID);
整體調用:
irq_set_handler_data(irq_num, (void *)gpio);
這裏的irq_num是經過irq_num = platform_get_irq(pdev, 0);獲取的系統配置文件裏面的irq配置。這個函數也簡單,實質爲:desc->irq_data.handler_data = data;
irq_set_chained_handler(irq_num, zynq_gpio_irqhandler);
這個函數實質爲:desc->handle_irq = handle;
最終調用關係爲:調用zynq_gpio_irqhandler,而後在該函數中經過調用generic_handle_irq來調用最終的handle_simple_irq。