当前位置:  开发笔记 > 运维 > 正文

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

如何解决《什么是linuxirq域名,为什么需要它们?》经验,为你挑选了1个好方法。

什么是irq域,我读了内核文档(https://www.kernel.org/doc/Documentation/IRQ-domain.txt),他们说:

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

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



1> Sam Protsenk..:

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

它在Documentation/IRQ-domain.txt的第一段中完美记录,因此我假设您已经知道它.如果不是 - 请询问有关该文档的不清楚之处.下面的文本说明了如何使用IRQ域API及其工作原理.

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

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

物理水平

为了完全理解进一步的解释,我们先来看看MAX732x的机制.数据表中的应用电路(我们的示例简化):

MAX7325典型应用电路

当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中断控制器.

设备树

让我们在设备树中声明上面的配置.我们可以使用Documentation/devicetree/bindings/gpio/gpio-max732x.txt中的绑定作为参考:

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>;
};

属性的含义如下:

interrupt-controllerproperty定义该设备生成中断; 需要进一步使用此节点,如interrupt-parent"某些设备"节点.

#interrupt-cells定义interrupts财产的格式; 在我们的例子中,它是2:1个单元用于行号,1个单元用于中断类型

interrupt-parentinterrupts属性描述中断线连接

假设我们有MAX7325的驱动程序和"Some device"的驱动程序.当然,两者都在CPU中运行.在"Some device"驱动程序中,当"某些器件"在MAX7325的P4引脚上改变电平时,我们要求事件中断.让我们首先在设备树中声明:

some_device: some_device@1c {
    reg = <0x1c>;
    interrupt-parent = <&expander>;
    interrupts = <4 IRQ_TYPE_EDGE_RISING>;
};

中断传播

现在我们可以做这样的事情(在"Some device"驱动程序中):

devm_request_threaded_irq(core->dev, core->gpio_irq, NULL,
        some_device_isr, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
        dev_name(core->dev), core);

some_device_isr()每当MAX7325的P4引脚电平从低电平变为高电平(上升沿)时,将被调用.这个怎么运作?从左到右,如果您查看上图:

"某些器件"在MAX7325的P4上改变电平

MAX7325的INT引脚电平变化

GPIO4模块配置为捕获这样的更改,因此它会生成GIC中断

GIC通知CPU

所有这些操作都发生在硬件级别上.让我们看看软件层面发生了什么.它实际上是倒退的(从图片的右侧到左侧):

CPU现在处于GIC中断处理程序的中断上下文中.从gic_handle_irq()调用handle_domain_irq(),然后调用generic_handle_irq().有关详细信息,请参阅Documentation/gpio/driver.txt.现在我们在SoC的GPIO控制器IRQ处理程序中.

SoC的GPIO驱动程序还调用generic_handle_irq()运行处理程序,该处理程序为每个特定引脚设置.例如,请参阅omap_gpio_irq_handler()中的完成方式.现在我们在MAX7325 IRQ处理程序中.

MAX7325 IRQ处理程序(此处)调用handle_nested_irq(),以便连接到MAX7325的设备的所有IRQ处理程序(在我们的例子中为"某些设备"IRQ处理程序)将在max732x_irq_handler()线程中调用

最后,调用"Some device"驱动程序的IRQ处理程序

IRQ域API

GIC驱动程序,GPIO驱动程序和MAX7325驱动程序 - 它们都使用IRQ域API将这些驱动程序表示为中断控制器.我们来看看它是如何在MAX732x驱动程序中完成的.它已添加到此提交中.通过阅读IRQ域文档并查看此提交,很容易弄清楚它是如何工作的.该提交中最有趣的部分是这一行(in max732x_irq_handler()):

handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain, level));

irq_find_mapping()将通过硬件IRQ号找到linux IRQ号(使用IRQ域映射功能).然后handle_nested_irq()将调用函数,它将运行"Some device"驱动程序的IRQ处理程序.

GPIOLIB_IRQCHIP

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

为了帮助处理GPIO irqchips的设置和管理以及相关的irqdomain和资源分配回调,gpiolib有一些帮助器可以通过选择GPIOLIB_IRQCHIPKconfig符号来启用:

gpiochip_irqchip_add():将一个irqchip添加到gpiochip.它会将struct gpio_chip*芯片传递给所有IRQ回调,因此回调需要将gpio_chip其嵌入其状态容器中并使用获取指向容器的指针container_of().(见Documentation/driver-model/design-patterns.txt)

gpiochip_set_chained_irqchip():gpio_chip为父IRQ 设置一个链式irq处理程序, 并传递struct gpio_chip*as处理程序数据.(注意处理程序数据,因为irqchip数据很可能被父irqchip使用!)这是针对链式芯片的.如果NULL作为处理程序传递,这也用于设置嵌套的irqchip .

此提交将IRQ域API转换为MAX732x驱动程序中的GPIOLIB_IRQCHIP API.

下一个问题

进一步讨论如下:

第2部分

第3部分

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有