目錄
1 設(shè)備樹里中斷節(jié)點(diǎn)的語法
1.1 設(shè)備樹里的中斷控制器
1.2?設(shè)備樹里使用中斷
2??設(shè)備樹里中斷節(jié)點(diǎn)的示例
3?在代碼中獲得中斷
3.1 對(duì)于 platform_device?
3.2??對(duì)于 I2C 設(shè)備、SPI 設(shè)備
3.3??調(diào)用 of_irq_get 獲得中斷號(hào)
3.4?對(duì)于 GPIO?
1 設(shè)備樹里中斷節(jié)點(diǎn)的語法
參考文檔:內(nèi)核 Documentation\devicetree\bindings\interrupt-controller\interrupts.txt
1.1 設(shè)備樹里的中斷控制器
中斷的硬件框圖如下:
?在硬件上,“中斷控制器”只有 GIC 這一個(gè),但是我們?cè)谲浖弦部梢园焉蠄D中的“GPIO”稱為“中斷控制器”。很多芯片有多個(gè) GPIO 模塊,比如 GPIO1、GPIO2 等等。所以軟件上的“中斷控制器”就有很多個(gè):GIC、GPIO1、GPIO2 等等。?
GPIO1 連接到 GIC,GPIO2 連接到 GIC,所以 GPIO1 的父親是 GIC,GPIO2的父親是 GIC。?
假設(shè) GPIO1 有 32 個(gè)中斷源,但是它把其中的 16 個(gè)匯聚起來向 GIC 發(fā)出一個(gè)中斷,把另外 16 個(gè)匯聚起來向 GIC 發(fā)出另一個(gè)中斷。這就意味著 GPIO1 會(huì)用到 GIC 的兩個(gè)中斷,會(huì)涉及 GIC 里的 2 個(gè) hwirq。?
這些層級(jí)關(guān)系、中斷號(hào)(hwirq),都會(huì)在設(shè)備樹中有所體現(xiàn)。?在設(shè)備樹中,中斷控制器節(jié)點(diǎn)中必須有一個(gè)屬性:interrupt-controller,表明它是“中斷控制器”。?
還必須有一個(gè)屬性:#interrupt-cells,表明引用這個(gè)中斷控制器的話需要多少個(gè) cell。?
#interrupt-cells 的值一般有如下取值:?
? ?#interrupt-cells=<1>?
別的節(jié)點(diǎn)要使用這個(gè)中斷控制器時(shí),只需要一個(gè) cell 來表明使用“哪一個(gè)中斷”。?
? ?#interrupt-cells=<2>?
別的節(jié)點(diǎn)要使用這個(gè)中斷控制器時(shí),需要一個(gè) cell 來表明使用“哪一個(gè)中斷”;?還需要另一個(gè) cell 來描述中斷,一般是表明觸發(fā)類型:?
第 2 個(gè) cell 的 bits[3:0] 用來表示中斷觸發(fā)類型(trigger type and level flags):
1 = low-to-high edge triggered,上升沿觸發(fā)
2 = high-to-low edge triggered,下降沿觸發(fā)
4 = active high level-sensitive,高電平觸發(fā)
8 = active low level-sensitive,低電平觸發(fā)
示例如下:?
vic: intc@10140000 {
compatible = "arm,versatile-vic";
interrupt-controller;
#interrupt-cells = <1>;
reg = <0x10140000 0x1000>;
};
如 果 中 斷 控 制 器 有 級(jí) 聯(lián) 關(guān) 系 , 下 級(jí) 的 中 斷 控 制 器 還 需 要 表 明 它 的“ interrupt-parent ” 是 誰 , 用 了 interrupt-parent ” 中 的 哪 一 個(gè)“interrupts”。
1.2?設(shè)備樹里使用中斷
一個(gè)外設(shè),它的中斷信號(hào)接到哪個(gè)“中斷控制器”的哪個(gè)“中斷引腳”,這個(gè)中斷的觸發(fā)方式是怎樣的??
這 3 個(gè)問題,在設(shè)備樹里使用中斷時(shí),都要有所體現(xiàn)。?
? ?interrupt-parent=<&XXXX>?
你要用哪一個(gè)中斷控制器里的中斷??
? ?interrupts?
你要用哪一個(gè)中斷??
Interrupts 里要用幾個(gè) cell,由 interrupt-parent 對(duì)應(yīng)的中斷控制器決定。在中斷控制器里有“#interrupt-cells”屬性,它指明了要用幾個(gè) cell來描述中斷。?
比如:?
i2c@7000c000 {
gpioext: gpio-adnp@41 {
compatible = "ad,gpio-adnp";
interrupt-parent = <&gpio>;
interrupts = <160 1>;
gpio-controller;
#gpio-cells = <1>;
interrupt-controller;
#interrupt-cells = <2>;
};
......
};
? ?新寫法:interrupts-extended?
一個(gè)“interrupts-extended”屬性就可以既指定“interrupt-parent”,也指定“interrupts”,比如:?
interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;
2??設(shè)備樹里中斷節(jié)點(diǎn)的示例
?從設(shè)備樹反推 IMX6ULL 的中斷體系,如下,比之前的框圖多了一個(gè)“GPC?INTC”:
?GPC ?INTC 的 英 文 是 : General ?Power ?Controller, ?Interrupt?Controller。它提供中斷屏蔽、中斷狀態(tài)查詢功能,實(shí)際上這些功能在 GIC 里也實(shí)現(xiàn)了,個(gè)人覺得有點(diǎn)多余。除此之外,它還提供喚醒功能,這才是保留它的原因。?
3?在代碼中獲得中斷
?之 前 我 們 提 到 過 , 設(shè) 備 樹 中 的 節(jié) 點(diǎn) 有 些 能 被 轉(zhuǎn) 換 為 內(nèi) 核 里 的platform_device,有些不能,回顧如下:
- 根節(jié)點(diǎn)下含有 compatile 屬性的子節(jié)點(diǎn),會(huì)轉(zhuǎn)換為 platform_device?
- 含有特定 compatile 屬性的節(jié)點(diǎn)的子節(jié)點(diǎn),會(huì)轉(zhuǎn)換為 platform_device?如果一個(gè)節(jié)點(diǎn)的 compatile 屬性,它的值是這 4 者之一:"simple-bus","simple-mfd","isa","arm,amba-bus", ?那么它的子結(jié)點(diǎn)(需含 compatile 屬性)也可以轉(zhuǎn)換為 platform_device。
- 總線 I2C、SPI 節(jié)點(diǎn)下的子節(jié)點(diǎn):不轉(zhuǎn)換為 platform_device?某個(gè)總線下到子節(jié)點(diǎn),應(yīng)該交給對(duì)應(yīng)的總線驅(qū)動(dòng)程序來處理, 它們不應(yīng)該被轉(zhuǎn)換為 platform_device。?
3.1 對(duì)于 platform_device?
一個(gè)節(jié)點(diǎn)能被轉(zhuǎn)換為 platform_device,如果它的設(shè)備樹里指定了中斷屬性,那么可以從 platform_device 中獲得“中斷資源”,函數(shù)如下,可以使用下列函數(shù)獲得 IORESOURCE_IRQ 資源,即中斷號(hào):?
/**
* platform_get_resource - get a resource for a device
* @dev: platform device
* @type: resource type // 取哪類資源?IORESOURCE_MEM、IORESOURCE_REG
* // IORESOURCE_IRQ 等
* @num: resource index // 這類資源中的哪一個(gè)?
*/
struct resource *platform_get_resource(struct platform_device *dev,
unsigned int type,
unsigned int num);
3.2??對(duì)于 I2C 設(shè)備、SPI 設(shè)備
對(duì)于 I2C 設(shè)備節(jié)點(diǎn),I2C 總線驅(qū)動(dòng)在處理設(shè)備樹里的 I2C 子節(jié)點(diǎn)時(shí),也會(huì)處理其中的中斷信息。一個(gè) I2C 設(shè)備會(huì)被轉(zhuǎn)換為一個(gè) i2c_client 結(jié)構(gòu)體,中斷號(hào)會(huì)保存在 i2c_client 的 irq 成員里,代碼如下(drivers/i2c/i2c-core.c):?
?對(duì)于 SPI 設(shè)備節(jié)點(diǎn),SPI 總線驅(qū)動(dòng)在處理設(shè)備樹里的 SPI 子節(jié)點(diǎn)時(shí),也會(huì)處理其中的中斷信息。一個(gè) SPI 設(shè)備會(huì)被轉(zhuǎn)換為一個(gè) spi_device 結(jié)構(gòu)體,中斷號(hào)會(huì)保存在 spi_device 的 irq 成員里,代碼如下(drivers/spi/spi.c):
?3.3??調(diào)用 of_irq_get 獲得中斷號(hào)
如果你的設(shè)備節(jié)點(diǎn)既不能轉(zhuǎn)換為 platform_device,它也不是 I2C 設(shè)備,不是 SPI 設(shè)備,那么在驅(qū)動(dòng)程序中可以自行調(diào)用 of_irq_get 函數(shù)去解析設(shè)備樹,得到中斷號(hào)。
3.4?對(duì)于 GPIO?
可以使用 gpio_to_irq 或 gpiod_to_irq 獲得中斷號(hào)。?舉例,假設(shè)在設(shè)備樹中有如下節(jié)點(diǎn):文章來源:http://www.zghlxwxcb.cn/news/detail-578165.html
gpio-keys {
compatible = "gpio-keys";
pinctrl-names = "default";
user {
label = "User Button";
gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
gpio-key,wakeup;
linux,code = <KEY_1>;
};
};
那么可以使用下面的函數(shù)獲得引腳和 flag:?
button->gpio = of_get_gpio_flags(pp, 0, &flags);?
bdata->gpiod = gpio_to_desc(button->gpio);?
再去使用 gpiod_to_irq 獲得中斷號(hào):?
irq = gpiod_to_irq(bdata->gpiod);?文章來源地址http://www.zghlxwxcb.cn/news/detail-578165.html
到了這里,關(guān)于Linux驅(qū)動(dòng)開發(fā)基礎(chǔ)_在設(shè)備樹中指定中斷以及在代碼中獲得中斷的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!