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 treen"); 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,./drivers/crypto/mxs-dcp.c: ret = devm_request_irq(dev,dcp_irq,./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,./drivers/crypto/picoxcell_crypto.c: if (devm_request_irq(&pdev->dev,irq->start,spacc_spacc_irq, 或硬编码硬件实际断言的内容: ./drivers/crypto/tegra-aes.c: err = devm_request_irq(dev,aes_irq,IRQF_TRIGGER_HIGH | 那么如何将这个属性从设备树干净地关联到实际的驱动程序呢? 解决方法
此外,我将展示如何在一些常见情况下从设备树获取IRQ号和IRQ标志:
>在I2C驱动程序中 在I2C驱动程序中 简而言之 如果您正在编写I2C驱动程序,则无需手动从DT读取IRQ参数.您可以依靠I2C内核为您填充IRQ参数: >在您的probe()函数中,client-> 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()的标志 换句话说,如果您没有将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_of_parse_and_map()并让devm_request_irq()为你处理标志(只是确保你没有向它传递触发器标志). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |