DTS設(shè)備樹中中斷節(jié)點(diǎn)的創(chuàng)建
提到中斷就必須了解到GIC,下面先了解一下GIC
一、GIC概念
? ? ? ??GIC(Generic Interrupt Controller)是ARM公司提供的一個(gè)通用的中斷控制器。GIC通過AMBA(Advanced Microcontroller Bus Architecture)這樣的片上總線連接到一個(gè)或者多個(gè)ARM processor上。
二、設(shè)備樹中中斷如何工作
? ? ? ?與遵循樹的自然結(jié)構(gòu)而進(jìn)行的地址轉(zhuǎn)換不同,機(jī)器上的任何設(shè)備都可以發(fā)起和終止中斷信號(hào)。另外地址的編址也不同于中斷信號(hào),前者是設(shè)備樹的自然表示,而后者者表現(xiàn)為獨(dú)立于設(shè)備樹結(jié)構(gòu)的節(jié)點(diǎn)之間的鏈接。描述中斷連接需要四個(gè)屬性:
?■??interrupt-controller?-?一個(gè)空的屬性定義(就是僅僅列出了該字符串,見下面) ?, 該節(jié)點(diǎn)作為一個(gè)接收中斷信號(hào)的設(shè)備。
?■ ?#interrupt-cells?- 這是一個(gè)中斷控制器節(jié)點(diǎn)的屬性。它聲明了該中斷控制器的中斷指示符中 cell 的個(gè)數(shù)(類似于 #address-cells 和 #size-cells)。
?■ ?interrupt-parent?- 這是一個(gè)設(shè)備節(jié)點(diǎn)的屬性,包含一個(gè)指向該設(shè)備連接的中斷控制器的 phandle。那些沒有 interrupt-parent 的節(jié)點(diǎn)則從它們的父節(jié)點(diǎn)中繼承該屬性。
?■ ?interrupts?- 一個(gè)設(shè)備節(jié)點(diǎn)屬性,包含一個(gè)中斷指示符的列表,對(duì)應(yīng)于該設(shè)備上的每個(gè)中斷輸出信號(hào)。
? ? ??中斷指示符是一個(gè)或多個(gè) cell 的數(shù)據(jù)(由 #interrupt-cells 指定),這些數(shù)據(jù)指定了該設(shè)備連接至哪些輸入中斷。在以下的例子中,大部分設(shè)備都只有一個(gè)輸出中斷,但也有可能在一個(gè)設(shè)備上有多個(gè)輸出中斷。一個(gè)中斷指示符的意義完全取決于與中斷控制器設(shè)備的 binding。每個(gè)中斷控制器可以決定使用幾個(gè) cell 來唯一的定義一個(gè)輸入中斷。
下面的代碼為添加了中斷連接:
1. /?{??
2. ??
3. ????compatible?=?"acme,coyotes-revenge";??
4. ????#address-cells?=?<1>;??
5. ????#size-cells?=?<1>;??
6. ????interrupt-parent?=?<&intc>;??
7. ??
8. ????cpus?{??
9. ????????#address-cells?=?<1>;??
10. ????????#size-cells?=?<0>;??
11. ????????cpu@0?{??
12. ????????????compatible?=?"arm,cortex-a9";??
13. ????????????reg?=?<0>;??
14. ????????};??
15. ??
16. ????????cpu@1?{??
17. ????????????compatible?=?"arm,cortex-a9";??
18. ????????????reg?=?<1>;??
19. ????????};??
20. ????};??
21. ??
40. ??
41. ????intc:?interrupt-controller@10140000?{??
42. ????????compatible?=?"arm,pl190";??
43. ????????reg?=?<0x10140000?0x1000?>;??
44. ????????interrupt-controller;?? ? ? ? ? ? ? ? ? ? ? //見上面,空的屬性,表明該節(jié)點(diǎn)是作為一個(gè)接收中斷的設(shè)備
45. ????????#interrupt-cells?=?<2>;??
46. ????};??
47. ??
48. ????spi@10115000?{??
49. ????????compatible?=?"arm,pl022";??
50. ????????reg?=?<0x10115000?0x1000?>;??
51. ????????interrupts?=?<?4?0?>;??
52. ????};??
53. ??
54. //external-bus的rangs屬性:
55. //external-bus的ranges屬性定義了經(jīng)過external-bus橋后的地址范圍如何映射到CPU的memory區(qū)域??床┛蛃bh的詳細(xì)講解
56. ????external-bus?{??
57. ????????#address-cells?=?<2>??
58. ????????#size-cells?=?<1>;??
59. ????????ranges?=?<0?0??0x10100000???0x10000 ? ? ? ??//?Chipselect?1,?Ethernet??
60. ? ? ? ? ? ? ? ? ? ? ?1?0??0x10160000???0x10000 ? ? ? ??//?Chipselect?2,?i2c?controller??
61. ? ? ? ? ? ? ? ? ? ? ?2?0??0x30000000???0x1000000>;?//?Chipselect?3,?NOR?Flash??
62. //解釋
63. //ranges屬性為一個(gè)地址轉(zhuǎn)換表。表中的每一行都包含了子地址、父地址、在自地址空間內(nèi)的區(qū)域大小。他們的大?。ò腸ell)分別由子節(jié)點(diǎn)的address-
64. //cells的值、父節(jié)點(diǎn)的address-cells的值和子節(jié)點(diǎn)
65. //的size-cells來決定。以第一行為例:
66. //0 0 兩個(gè)cell,由子節(jié)點(diǎn)external-bus的address-cells=<2>決定;
67. //0x10100000 一個(gè)cell,由父節(jié)點(diǎn)的address-cells=<1>決定0x10000 一個(gè)cell,由子節(jié)點(diǎn)external-bus的size-cells=<1>決定。
68. //最終第一行說明的意思就是:片選0 (注意有片選,這應(yīng)該是外設(shè)的一個(gè)特點(diǎn)),偏移0(選中了網(wǎng)卡),被映射到CPU地址空間的0x10100000~0x10110000中,地址長度為0x10000。
69. ?
70. ??
71. ????????ethernet@0,0?{??
72. ????????????compatible?=?"smc,smc91c111";??
73. ????????????reg?=?<0?0?0x1000>;??
74. ????????????interrupts?=?<?5?2?>;??
75. ????????};??
76. ??
77. ????????i2c@1,0?{??
78. ????????????compatible?=?"acme,a1234-i2c-bus";??
79. ????????????#address-cells?=?<1>;??
80. ????????????#size-cells?=?<0>;??
81. ????????????reg?=?<1?0?0x1000>;??
82. ????????????interrupts?=?<?6?2?>;??
83. ??
84. ????????????rtc@58?{??
85. ????????????????compatible?=?"maxim,ds1338";??
86. ????????????????reg?=?<58>;??
87. ????????????????interrupts?=?<?7?3?>;??
88. ????????????};??
89. ????????};??
90. ??
91. ????????flash@2,0?{??
92. ????????????compatible?=?"samsung,k8f1315ebm",?"cfi-flash";??
93. ????????????reg?=?<2?0?0x4000000>;??
94. ????????};??
95. ????};??
96. };??
需要注意的事情:
■ 這個(gè)機(jī)器只有一個(gè)中斷控制器:interrupt-controller@10140000。
■ 中斷控制器節(jié)點(diǎn)上添加了‘inc:’標(biāo)簽,該標(biāo)簽用于給根節(jié)點(diǎn)的 interrupt-parent 屬性分配一個(gè) phandle。這個(gè) interrupt-parent 將成為本系統(tǒng)的默認(rèn)值,因?yàn)樗械淖庸?jié)點(diǎn)都將繼承它,除非顯示覆寫這個(gè)屬性。
■?每個(gè)設(shè)備使用 interrupts 屬性來不同的中斷輸入線。
■ #interrupt-cells 是 2,所以每個(gè)中斷指示符都有 2 個(gè) cell。本例使用一種通用的模式,也就是用第一個(gè) cell 來編碼中斷線號(hào);然后用第二個(gè) cell?編碼標(biāo)志位,比如高電平/低電平有效,或者邊緣/水平觸發(fā)。對(duì)于任何給定的中斷控制器,請(qǐng)參考該控制器的?binding 文檔以了解指示符如何編碼。
三、GIC DTS描述
1、中斷系統(tǒng)概述
? ? 對(duì)于中斷系統(tǒng),主要有三個(gè)角色:
(1)processor:主要用于處理中斷;
(2)Interrupt Generating Device:通過硬件的interrupt line表明自身需要處理器的進(jìn)一步處理(例如有數(shù)據(jù)到來、異常狀態(tài)等)
(3)interrupt controller:負(fù)責(zé)收集各個(gè)外設(shè)的異步事件,用有序、可控的方式通知一個(gè)或者多個(gè)processor。
2、DTS如何描述Interrupt Generating Device
? ? ?對(duì)于Interrupt Generating Device,我們需要定義下面兩個(gè)屬性:
(1)?Interrupt屬性:該屬性主要描述了中斷的HW interrupt ID以及類型。
(2)interrupt-parent 屬性:該屬性主要描述了該設(shè)備的interrupt request line連接到哪一個(gè)interrupt controller。
我們以一個(gè)簡單的串口為例子,?
uart3: serial@48020000 {
? ? ? ?compatible = "ti,omap4-uart";
? ? ? ?reg = <0x48020000 0x100="">;
? ? ???interrupts = <GIC_SPI ?74 ?IRQ_TYPE_LEVEL_HIGH>;
? ? ? ?ti,hwmods = "uart3";
? ? ? ?clock-frequency = <48000000>;
};
? ? 對(duì)于uart3,interrupts屬性用3個(gè)cell(對(duì)于device tree,cell是指由32bit組成的一個(gè)信息單位)表示。GIC_SPI 描述了interrupt type。
對(duì)于GIC,它可以管理4種類型的中斷:
1)外設(shè)中斷(Peripheral interrupt)
? ? ? ?根據(jù)目標(biāo)CPU的不同,外設(shè)的中斷可以分成PPI(Private Peripheral Interrupt)和SPI(Shared Peripheral Interrupt)。PPI只能分配給一個(gè)確定的processor,而SPI可以由Distributor將中斷分配給一組Processor中的一個(gè)進(jìn)行處理。外設(shè)類型的中斷一般通過一個(gè)interrupt request line的硬件信號(hào)線連接到中斷控制器,可能是電平觸發(fā)的(Level-sensitive),也可能是邊緣觸發(fā)的(Edge-triggered)。
2)軟件觸發(fā)的中斷(SGI,Software-generated?interrupt)
? ? ? ?軟件可以通過寫GICD_SGIR寄存器來觸發(fā)一個(gè)中斷事件,這樣的中斷,可以用于processor之間的通信。
3)虛擬中斷(Virtual interrupt)和 Maintenance interrupt。
? ? ?這兩種中斷和本文無關(guān),不再贅述。
? ? ?在DTS中,外設(shè)的interrupt type有兩種,一種是SPI,另外一種是PPI。SGI用于processor之間的通信,和外設(shè)無關(guān)。? ? ?uart3的interrupt屬性中的74表示該外設(shè)使用的GIC interrupt ID號(hào)。GIC最大支持1020個(gè)HW interrupt ID,具體的ID分配情況如下:1)ID0~ID31是用于分發(fā)到一個(gè)特定的process的interrupt。標(biāo)識(shí)這些interrupt不能僅僅依靠ID,因?yàn)楦鱾€(gè)interrupt source都用同樣的ID0~ID31來標(biāo)識(shí),因此識(shí)別這些interrupt需要interrupt ID + CPU interface number。ID0~ID15用于SGI,ID16~ID31用于PPI。PPI類型的中斷會(huì)送到指定的process上,和其他的process無關(guān)。SGI是通過寫GICD_SGIR寄存器而觸發(fā)的中斷。Distributor通過processor source ID、中斷ID和target processor ID來唯一識(shí)別一個(gè)SGI。2)ID32~ID1019用于SPI。uart3的interrupt屬性中的IRQ_TYPE_LEVEL_HIGH用來描述觸發(fā)類型。
3、DTS如何描述GIC
? ? ?linux-3.14\arch\arm\boot\dts\exynos4412.dtsi文件中
1. #include?"exynos4x12.dtsi"??
2. /{????????
3. ????compatible?=?"samsung,exynos4412";???????
4. ????gic:?interrupt-controller@10490000?{????????
5. ????????cpu-offset?=?<0x4000>;???
6. ????};???????
7. ??
8. ????interrupt-controller@10440000?{??????????????
9. ????????samsung,combiner-nr?=?<20>;??????????????
10. ????????interrupts?=????<0?0?0>,?<0?1?0>,?<0?2?0>,?<0?3?0>,?????????????????????????
11. ???????????????? ? ? ? ?<0?4?0>,?<0?5?0>,?<0?6?0>,?<0?7?0>,?????????????????????????
12. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <0?8?0>,?<0?9?0>,?<0?10?0>,?<0?11?0>,????????????????????????
13. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <0?12?0>,?<0?13?0>,?<0?14?0>,?<0?15?0>,??????????????????????????
14. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <0?107?0>,?<0?108?0>,?<0?48?0>,?<0?42?0>;???????
15. ????};??
16. };??
a -- compatible屬性
? ? ??compatible屬性用來描述GIC的programming model。該屬性的值是string list,定義了一系列的modle(每個(gè)string是一個(gè)model)。這些字符串列表被操作系統(tǒng)用來選擇用哪一個(gè)driver來驅(qū)動(dòng)該設(shè)備。
? ? ?假設(shè)定義該屬性:compatible = “a廠商,p產(chǎn)品”,?“標(biāo)準(zhǔn)bbb類型設(shè)備”。那么linux kernel可能首先使用“a廠商,p產(chǎn)品”來匹配適合的driver,如果沒有匹配到,那么使用字符串“標(biāo)準(zhǔn)bbb類型設(shè)備”來繼續(xù)尋找適合的driver。
? ? ?compatible屬性有兩個(gè)應(yīng)用場景:
1)對(duì)于root node,compatible屬性是用來匹配machine type的(參考Device Tree相關(guān)文檔)
2)對(duì)于普通的HW block的節(jié)點(diǎn)(硬件模塊節(jié)點(diǎn)如中斷控制器),例如interrupt-controller,compatible屬性是用來匹配適合的driver的。
b -- interrupt-controller?
? ? ? ?interrupt-controller這個(gè)沒有定義value的屬性用來表明本設(shè)備節(jié)點(diǎn)就是一個(gè)interrupt controller。理解#interrupt-cells這個(gè)屬性需要理解interrupt specifier和interrupt domain這兩個(gè)概念。interrupt specifier其實(shí)就是外設(shè)interrupt的屬性值,對(duì)于uart3而言,其interrupt specifier就是<GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,也就是說,interrupt specifier定義了一個(gè)外設(shè)產(chǎn)生中斷的規(guī)格(HW interrupt ID + interrupt type)。
? ? ?具體如何解析interrupt specifier?這個(gè)需要限定在一定的上下文中,不同的interrupt controller會(huì)有不同的解釋。因此,對(duì)于一個(gè)包含多個(gè)interrupt controller的系統(tǒng),每個(gè)interrupt controller及其相連的外設(shè)組成一個(gè)interrupt domain,各個(gè)外設(shè)的interrupt specifier只能在屬于它的那個(gè)interrupt domain中得到解析。#interrupt-cells定義了在該interrupt domain中,用多少個(gè)cell來描述一個(gè)外設(shè)的interrupt specifier。
c -- reg
? ? ??reg屬性定義了GIC的memory map的地址.
三、GIC的HW block diagram描述
1、Distributor
? ? ??Distributor的主要的作用是檢測各個(gè)interrupt source的狀態(tài),控制各個(gè)interrupt source的行為,分發(fā)各個(gè)interrupt source產(chǎn)生的中斷事件到各個(gè)processor。
Distributor對(duì)中斷的控制包括:
1)中斷enable或者disable的控制。Distributor對(duì)中斷的控制分成兩個(gè)級(jí)別。一個(gè)是全局中斷的控制。一旦disable了全局的中斷,那么任何的interrupt source產(chǎn)生的interrupt event都不會(huì)被傳遞到CPU interface。另外一個(gè)級(jí)別是對(duì)針對(duì)各個(gè)interrupt source進(jìn)行控制,disable某一個(gè)interrupt source會(huì)導(dǎo)致該interrupt event不會(huì)分發(fā)到CPU interface,但不影響其他interrupt source產(chǎn)生interrupt event的分發(fā)。
2)控制中斷事件分發(fā)到processor。一個(gè)interrupt事件可以分發(fā)給一個(gè)processor,也可以分發(fā)給若干個(gè)processor。
3)優(yōu)先級(jí)控制。
4)interrupt屬性設(shè)定。例如是level-sensitive還是edge-triggered,是屬于group 0還是group 1。
? ???Distributor可以管理若干個(gè)interrupt source,這些interrupt source用ID來標(biāo)識(shí),我們稱之interrupt ID。
2、CPU interface
? ? ? CPU interface這個(gè)block主要用于和processor進(jìn)行接口。該block的主要功能包括:
1)enable或者disable
? ? ?對(duì)于ARM,CPU interface block和processor之間的中斷信號(hào)線是nIRQ和nFIQ這兩個(gè)signal。如果disable了中斷,那么即便是Distributor分發(fā)了一個(gè)中斷事件到CPU interface,但是也不會(huì)assert指定的nIRQ或者nFIQ通知processor。
2)ackowledging中斷
? ? ?processor會(huì)向CPU interface block應(yīng)答中斷,中斷一旦被應(yīng)答,Distributor就會(huì)把該中斷的狀態(tài)從pending狀態(tài)修改成active。如果沒有后續(xù)pending的中斷,那么CPU interface就會(huì)deassert nIRQ或者nFIQ的signal。如果在這個(gè)過程中又產(chǎn)生了新的中斷,那么Distributor就會(huì)把該中斷的狀態(tài)從pending狀態(tài)修改成pending and active。這時(shí)候,CPU interface仍然會(huì)保持nIRQ或者nFIQ信號(hào)的asserted狀態(tài),也就是向processor signal下一個(gè)中斷。
3)中斷處理完畢的通知
? ? ?當(dāng)interrupt handler處理完了一個(gè)中斷的時(shí)候,會(huì)向?qū)慍PU interface的寄存器從而通知GIC CPU已經(jīng)處理完該中斷。做這個(gè)動(dòng)作一方面是通知Distributor將中斷狀態(tài)修改為deactive,另外一方面,如果一個(gè)中斷沒有完成處理,那么后續(xù)比該中斷優(yōu)先級(jí)低的中斷不會(huì)assert到processor。一旦標(biāo)記中斷處理完成,被block掉的那些比當(dāng)前優(yōu)先級(jí)低的中斷就會(huì)遞交給processor。
4)設(shè)定priority mask
? ? ?通過priority mask,可以mask掉一些優(yōu)先級(jí)比較低的中斷,這些中斷不會(huì)通知到CPU。
5)設(shè)定preemption的策略
6)在多個(gè)中斷事件同時(shí)到來的時(shí)候,選擇一個(gè)優(yōu)先級(jí)最高的通知processor