什么是linux irq域,为什么需要它们?

什么是linux irq域,为什么需要它们?,linux,linux-kernel,linux-device-driver,embedded-linux,interrupt,max732x.c,Linux,Linux Kernel,Linux Device Driver,Embedded Linux,Interrupt,Max732x.c,什么是irq域,我阅读了内核文档()它们说: 注册为唯一irqchips的中断控制器的数量 显示上升趋势:例如,不同类型的子驱动程序 例如GPIO控制器避免重新实现相同的回调 通过对中断进行建模,将机制作为IRQ核心系统 处理器作为irqchips,即实际上是级联中断控制器 如何将GPIO控制器称为中断控制器?我在include/linux/irqdomain.h中找到了一条评论: 中断控制器“域”数据结构。这可以定义为 irq域控制器。也就是说,它处理 给定中断域的硬件和虚拟中断号 我认为它所

什么是irq域,我阅读了内核文档()它们说:

注册为唯一irqchips的中断控制器的数量 显示上升趋势:例如,不同类型的子驱动程序 例如GPIO控制器避免重新实现相同的回调 通过对中断进行建模,将机制作为IRQ核心系统 处理器作为irqchips,即实际上是级联中断控制器


如何将GPIO控制器称为中断控制器?

我在include/linux/irqdomain.h中找到了一条评论:

中断控制器“域”数据结构。这可以定义为 irq域控制器。也就是说,它处理 给定中断域的硬件和虚拟中断号

我认为它所指的实际结构是irq_域

什么是linux irq域,为什么需要它们

它在的第一段中有很好的记录,所以我假设你已经知道了。如果没有--请询问关于该文档的哪些内容不清楚。下面的文本解释了如何使用IRQ域API及其工作原理

如何将GPIO控制器称为中断控制器

让我以驱动程序作为参考()来回答这个问题。它是一个GPIO驱动程序,它的作用也类似于中断控制器,所以它应该是IRQ域API如何工作的一个很好的例子

身体水平 为了完全理解进一步的解释,让我们首先了解MAX732x力学。应用电路来自(简化为我们的示例):

当P0-P7引脚上的电压电平发生变化时,MAX7325将在INT引脚上产生中断。驱动器(在SoC上运行)可以通过I2C(SCL/SDA引脚)读取P0-P7引脚的状态,并为每个P0-P7引脚生成单独的中断。这就是为什么这个驱动程序充当中断控制器的原因

考虑下一个配置:

“某些设备”改变P4引脚的电平,诱使MAX7325产生中断。来自MAX7325的中断连接到GPIO4 IP核(SoC内部),它使用该GPIO4模块的第29行通知CPU中断。所以我们可以说MAX7325是级联到GPIO4控制器的。GPIO4还充当中断控制器,并级联到GIC中断控制器

设备树 让我们在设备树中声明上述配置。我们可以使用中的绑定作为参考:

expander: max7325@6d {
    compatible = "maxim,max7325";
    reg = <0x6d>;

    gpio-controller;
    #gpio-cells = <2>;

    interrupt-controller;
    #interrupt-cells = <2>;

    interrupt-parent = <&gpio4>;
    interrupts = <29 IRQ_TYPE_EDGE_FALLING>;
};
中断传播 现在我们可以这样做(在“某些设备”驱动程序中):

devm\u请求\u线程化\u irq(core->dev,core->gpio\u irq,NULL,
一些设备isr,IRQF触发上升,IRQF一次性,
设备名称(核心->设备),核心);
当MAX7325的P4引脚上的电平从低到高(上升沿)时,每次都会调用一些设备isr()。它是如何工作的?从左到右,如果您查看上图:

  • “某些设备”更改MAX7325的P4上的电平
  • MAX7325更改其INT引脚的电平
  • GPIO4模块被配置为捕捉这样的变化,所以它生成GIC的中断
  • GIC通知CPU
所有这些操作都发生在硬件级别。让我们看看在软件层面上发生了什么。它实际上是向后的(从图中的右向左):

  • CPU现在处于GIC中断处理程序中的中断上下文中。它从中调用
    handle\u domain\u irq()
    ,然后调用
    generic\u handle\u irq()
    。有关详细信息,请参阅。现在我们在SoC的GPIO控制器IRQ处理器中
  • SoC的GPIO驱动程序还调用
    generic\u handle\u irq()
    来运行为每个特定管脚设置的处理程序。例如,请参见在中是如何完成的。现在我们使用的是MAX7325 IRQ处理程序
  • MAX7325 IRQ处理程序()调用
    handle\u-nested\u-IRQ()
    ,以便连接到MAX7325的设备的所有IRQ处理程序(在我们的例子中为“某些设备”IRQ处理程序)都将在
    max732x\u-IRQ\u处理程序()
    线程中调用
  • 最后,调用“某个设备”驱动程序的IRQ处理程序
IRQ域API GIC驱动程序、GPIO驱动程序和MAX7325驱动程序——它们都使用IRQ域API将这些驱动程序表示为中断控制器。让我们看看它是如何在Max 732 x驱动程序中完成的。它是在提交中添加的。只需阅读IRQ域文档并查看此提交,就很容易了解它是如何工作的。提交过程中最有趣的部分是这一行(在
max732x\u irq\u handler()
中):

handle_nested_irq(irq_find_映射(chip->gpio_chip.irqdomain,level));
irq\u find\u mapping()
将按硬件irq编号查找linux irq编号(使用irq domainmapping函数)。然后将调用
handle\u nested\u irq()
函数,该函数将运行“某个设备”驱动程序的irq处理程序

GPIOLIB_IRQCHIP 由于许多GPIO驱动程序以相同的方式使用IRQ域,因此决定将该代码提取到GPIOLIB框架,更具体地说,提取到GPIOLIB_IRQCHIP。从
文档/gpio/driver.txt

帮助处理GPIO irqchips和 关联的irqdomain和资源分配回调,gpiolib 可通过选择
GPIOLIB\u IRQCHIP
Kconfig启用的一些帮助程序 符号:

  • gpiochip\u irqchip\u add()
    :将irqchip添加到gpiochip。它会过去的 芯片的
    struct gpio_chip*
    用于所有IRQ回调,因此回调 需要将
    gpio_芯片
    嵌入其状态容器并获取指针 使用
    container\u of()
    连接到容器。 (请参见
    文档/driver model/design patterns.txt

  • gpiochip\u set\u chained\u irqchip()
    :为
    gpio_芯片
    来自父IRQ,并将
    struct gpio_芯片*
    作为处理程序传递 数据。(注意处理程序数据,因为irqchi
    some_device: some_device@1c {
        reg = <0x1c>;
        interrupt-parent = <&expander>;
        interrupts = <4 IRQ_TYPE_EDGE_RISING>;
    };