linux不用裝置樹寫中斷,linux-kernel – 將裝置樹中斷標誌對映到devm_request_irq
我目前正在為
Linux使用PowerPC編寫裝置驅動程式.
裝置樹條目如下:
// PPS Interrupt client
pps_hwirq {
compatible = "pps-hwirq";
interrupts = <17 0x02>; // IPIC 17 = IRQ1, 0x02 = falling edge
interrupt-parent = < &ipic >;
};
0x02標誌非常重要 – PPS與下降沿對齊,但這在GPS接收器上不是通用的,因此應該是可配置的.
在驅動程式的probe()函式中,獲取IRQ編號很簡單:
hwirq = irq_of_parse_and_map(np, 0);
if (hwirq == NO_IRQ) {
dev_err(&pdev->dev, "No interrupt found in the device tree\n");
return -EINVAL;
}
但是如何將IRQ標誌從裝置樹對映到驅動程式?
/* ****TODO****: Get the interrupt flags from the device tree
* For now, hard code to suit my problem, but since this differs
* by GPS receiver, it should be configurable.
*/
flags = IRQF_TRIGGER_FALLING;
/* register IRQ interrupt handler */
ret = devm_request_irq(&pdev->dev, data->irq, pps_hwint_irq_handler,
flags, data->info.name, data);
不幸的是,在樹中實際執行此工作的示例很少 – 如果有的話 – 大多數將此標誌保留為0(保持原樣) – 這是grep for devm_request_irq時的結果片段,注意標誌的值:
./drivers/crypto/mxs-dcp.c: ret = devm_request_irq(dev, dcp_vmi_irq, mxs_dcp_irq, 0,
./drivers/crypto/mxs-dcp.c: ret = devm_request_irq(dev, dcp_irq, mxs_dcp_irq, 0,
./drivers/crypto/omap-sham.c: err = devm_request_irq(dev, dd->irq, dd->pdata->intr_hdlr,
./drivers/crypto/omap-aes.c: err = devm_request_irq(dev, irq, omap_aes_irq, 0,
./drivers/crypto/picoxcell_crypto.c: if (devm_request_irq(&pdev->dev, irq->start, spacc_spacc_irq, 0,
或硬編碼硬體實際斷言的內容:
./drivers/crypto/tegra-aes.c: err = devm_request_irq(dev, dd->irq, aes_irq, IRQF_TRIGGER_HIGH |
那麼如何將這個屬性從裝置樹幹淨地關聯到實際的驅動程式呢?
此外,我將展示如何在一些常見情況下從裝置樹獲取IRQ號和IRQ標誌:
>在I2C驅動程式中
>在平臺驅動程式中
>手動
在I2C驅動程式中
簡而言之
如果您正在編寫I2C驅動程式,則無需手動從DT讀取IRQ引數.您可以依靠I2C核心為您填充IRQ引數:
>在您的probe()函式中,client-> irq將包含IRQ編號
> devm_request_irq()將自動使用DT的IRQ標誌(只是不要將任何IRQ觸發器標誌傳遞給該函式).
細節
讓我們看一下i2c_device_probe()函式(它是呼叫驅動程式的probe()函式的地方):
static int i2c_device_probe(struct device *dev)
{
...
if (dev->of_node) {
...
irq = of_irq_get(dev->of_node, 0);
}
...
client->irq = irq;
...
status = driver->probe(client, i2c_match_id(driver->id_table, client));
}
因此,client-> irq已經在驅動程式的探測函式中包含IRQ編號.
至於IRQ標誌:of_irq_get()(在上面的程式碼中)最終呼叫irqd_set_trigger_type(),它在內部儲存IRQ標誌(從裝置樹讀取)作為中斷號.因此,當您呼叫devm_request_irq()時,它最終會在__setup_irq()中結束,然後執行下一步:
/*
* If the trigger type is not specified by the caller,
* then use the default for this interrupt.
*/
if (!(new->flags & IRQF_TRIGGER_MASK))
new->flags |= irqd_get_trigger_type(&desc->irq_data);
哪裡:
> new-> flags包含您提供給devm_request_irq()的標誌
> irqd_get_trigger_type()返回從DT獲得的標誌
換句話說,如果您沒有將IRQ標誌傳遞給devm_request_irq()(例如傳遞0),它將使用從裝置樹獲得的IRQ標誌.
有關詳細資訊,請參閱this question.
在平臺驅動程式
您可以使用platform_get_irq()來獲取IRQ編號.它還儲存(內部)從DT獲得的IRQ標誌,因此如果將flags = 0傳遞給devm_request_irq(),將使用來自DT的標誌.
手動
如果您的驅動程式不依賴於核心框架,則必須手動獲取IRQ值:
> IRQ編號可以通過irq_of_parse_and_map()獲得(如您所述);此函式不僅返回IRQ號,還儲存IRQ號的IRQ標誌(最終通過呼叫irqd_set_trigger_type());儲存的IRQ標誌將在devm_request_irq()中自動使用,如果您沒有向其傳遞IRQ觸發器型別(例如,您可以傳遞flags = 0)
> IRQ標誌可以在irq_get_trigger_type()獲得,但僅在執行irq_of_parse_and_map()之後
所以可能你只需要執行irq_of_parse_and_map()並讓devm_request_irq()為你處理標誌(只是確保你沒有向它傳遞觸發器標誌).
【轉】https://blog.csdn.net/weixin_28949355/article/details/116775031