Dam*_*ien 5 linux-device-driver linux-kernel device-tree
我目前正在为Linux使用PowerPC编写设备驱动程序.
设备树条目如下:
// PPS Interrupt client
pps_hwirq {
compatible = "pps-hwirq";
interrupts = <17 0x02>; // IPIC 17 = IRQ1, 0x02 = falling edge
interrupt-parent = < &ipic >;
};
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
但是如何将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);
Run Code Online (Sandbox Code Playgroud)
不幸的是,在树中实际执行此工作的示例很少 - 如果有的话 - 大多数将此标志保留为0(保持原样) - 这里是结果的片段,grep用于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,
Run Code Online (Sandbox Code Playgroud)
或硬编码硬件实际断言的内容:
./drivers/crypto/tegra-aes.c: err = devm_request_irq(dev, dd->irq, aes_irq, IRQF_TRIGGER_HIGH |
Run Code Online (Sandbox Code Playgroud)
那么如何将这个属性从设备树干净地关联到实际的驱动程序呢?
此外,我将展示如何在一些常见情况下从设备树获取IRQ号和IRQ标志:
如果您正在编写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));
}
Run Code Online (Sandbox Code Playgroud)
因此,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);
Run Code Online (Sandbox Code Playgroud)
哪里:
new->flags 包含您提供的标志 devm_request_irq()irqd_get_trigger_type() 返回从DT获得的标志换句话说,如果你没有传递IRQ标志devm_request_irq()(例如传递0),它将使用从设备树获得的IRQ标志.
有关详细信息,请参阅此问题.
您可以使用platform_get_irq()获取IRQ号码.它还存储(内部)从DT获得的IRQ标志,因此如果传递flags=0给devm_request_irq()DT,将使用来自DT的标志.
如果您的驱动程序不依赖于内核框架,则必须手动获取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()为您处理标志(只需确保不向其传递触发器标志).
| 归档时间: |
|
| 查看次数: |
4554 次 |
| 最近记录: |