Linux Zynq GPIO中斷

註冊中斷:對每一個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。

相關文章
相關標籤/搜索