今天呢,我們就來具體的講一下GIC的驅動源碼啦,這個才是重點來著,我們來看看:
GIC中的重要函數和結構體:
沿著中斷的處理流程,GIC涉及這4個重要部分:
-
CPU從異常向量表中調用handle_arch_irq,這個函數指針是有GIC驅動設置的
-
GIC才知道怎么判斷發生的是哪個GIC中斷
-
-
從GIC獲得hwirq后,要轉換為virq:需要有GIC Domain
-
調用irq_desc[virq].handle_irq函數:這也應該由GIC驅動提供
-
處理中斷時,要屏蔽中斷、清除中斷等:這些函數保存在irq_chip里,由GIC驅動提供
從硬件上看,GIC的功能是什么?
-
可以使能、屏蔽中斷
-
發生中斷時,可以從GIC里判斷是哪個中斷
在內核里,使用gic_chip_data結構體表示GIC,gic_chip_data里有什么?
-
irq_chip:中斷使能、屏蔽、清除,放在irq_chip中的各個函數里實現
-
irq_domain
-
申請中斷時
-
在設備樹里指定hwirq、flag,可以使用irq_domain的函數來解析設備樹
-
根據hwirq可以分配virq,把(hwirq, virq)存入irq_domain中
-
-
發生中斷時,從GIC讀出hwirq,可以通過irq_domain找到virq,從而找到處理函數
-
所以,GIC用gic_chip_data來表示,gic_chip_data中重要的成員是:irq_chip、irq_domain。
GIC初始化過程:
內核支持多種GIC:
按照設備樹的套路:
-
驅動程序注冊platform_driver
-
它的of_match_table里有多個of_device_id,表示能支持多個設備
-
有多種版本的GIC,在內核為每一類GIC定義一個結構體of_device_id,并放在一個段里:
把宏IRQCHIP_DECLARE
展開:
在設備樹里指定GIC:
在設備樹中指定GIC,內核驅動程序根據設備樹來選擇、初始化GIC。
drivers\irqchip\irqchip.c
中并沒有定義一個platform_driver,但是套路是一樣的。
調用過程:
of_irq_init:
-
內核有一個__irqchip_of_table數組,里面有多個of_device_id,表示多種GIC
-
要使用哪類GIC?在設備樹里指定
-
根據設備樹,找到__irqchip_of_table樹組中對應的項,調用它的初始化函數
-
IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
-
?
申請GIC中斷:
在設備樹里指定中斷:
內核對設備樹的處理:
函數調用過程如下,使用圖片形式可以一目了然:
函數調用過程如下,使用文字格式方便復制:
-
為設備樹節點分配設備
解析設備樹映射中斷: irq_of_parse_and_map
下面我們來看看圖片來進行分析:
首先的話,就是GIC去遍歷自己的寄存器,判斷發生了哪個中斷,這個是在中斷向量表里面的,匯編來著,小編也沒有很明白(唯唯諾諾)
第二個就是那個irq_domain的關系是怎么去建立的,
他會調用里面的translate函數,去解析設備樹
然后為他的hwirq找到一個空閑的virq,然后記錄在domain里面,最后去調用domain里面的alloc函數去處理
allow主要是包括建立mapping關系,然后就是就是注冊那些irq_data,這些在前面已經定義好了
這邊就是提供irq_chip了,那么到這里,我們就徹底講完啦,其實GIC也沒有想象的那么復雜,邏輯性很強,嘿嘿,完結,撒花(doge.)
?
?