gpt4 book ai didi

linux-kernel - 将设备树中断标志映射到 devm_request_irq

转载 作者:行者123 更新时间:2023-12-04 14:56:02 26 4
gpt4 key购买 nike

我目前正在为 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 时的结果片段对于 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=0devm_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()为您处理标志(只要确保您没有将触发标志传递给它)。
  • 关于linux-kernel - 将设备树中断标志映射到 devm_request_irq,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40011799/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com