什么是irq域,我阅读了内核文档(https://www.kernel.org/doc/Documentation/IRQ-domain.txt)他们说:
GPIO Controller 如何称为中断 Controller ?
最佳答案
它已在Documentation/IRQ-domain.txt的第一段中完美记录,因此我假设您已经知道它。如果不是,请询问有关该文档的不清楚之处。下面的文本说明了如何使用IRQ域API及其工作方式。
让我使用max732x.c驱动程序作为引用(driver code)回答这个问题。它是一个GPIO驱动程序,它也像中断 Controller 一样工作,因此它应该是IRQ域API工作原理的一个很好的例子。
body 水平
为了完全理解进一步的解释,让我们首先了解一下MAX732x的原理。 datasheet的应用电路(在我们的示例中已简化):
当P0-P7引脚上的电压电平发生变化时,MAX7325将在INT引脚上产生中断。驱动程序(在SoC上运行)可以通过I2C(SCL/SDA引脚)读取P0-P7引脚的状态,并为每个P0-P7引脚生成单独的中断。这就是为什么此驱动程序充当中断 Controller 的原因。
考虑下一个配置:
“某些设备”改变P4引脚上的电平,诱使MAX7325产生中断。来自MAX7325的中断连接到GPIO4 IP内核(在SoC内部),它使用该GPIO4模块的29号线通知CPU有关中断的信息。因此,可以说MAX7325是级联的至GPIO4 Controller 。 GPIO4还充当中断 Controller ,并且级联到GIC中断 Controller 。
设备树
让我们在设备树中声明以上配置。我们可以使用Documentation/devicetree/bindings/gpio/gpio-max732x.txt的绑定(bind)作为引用:
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-controller
属性定义设备生成中断。进一步需要将此节点用作“某些设备”节点中的interrupt-parent
。 #interrupt-cells
定义interrupts
属性的格式;在我们的例子中,它是2
:1个单元格代表行号,1个单元格代表中断类型interrupt-parent
和interrupts
属性描述中断线连接假设我们有MAX7325的驱动程序和“某些设备”的驱动程序。当然,两者都在CPU中运行。在“某些设备”驱动程序中,当“某些设备”更改MAX7325的P4引脚上的电平时,我们希望请求事件中断。让我们首先在设备树中声明:
some_device: some_device@1c {
reg = <0x1c>;
interrupt-parent = <&expander>;
interrupts = <4 IRQ_TYPE_EDGE_RISING>;
};
中断传播
现在,我们可以执行以下操作(在“某些设备”驱动程序中):
devm_request_threaded_irq(core->dev, core->gpio_irq, NULL,
some_device_isr, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
dev_name(core->dev), core);
每当MAX7325的P4引脚上的电平从低到高(上升沿)时,就会调用
some_device_isr()
。这个怎么运作?从左到右,如果您看向上方的图片,请执行以下操作:所有这些 Action 都是在硬件级别上发生的。让我们看看在软件级别上发生了什么。实际上,它向后退(从图片的右到左):
handle_domain_irq()
,然后又调用generic_handle_irq()
。有关详细信息,请参见Documentation/gpio/driver.txt。现在我们在SoC的GPIO Controller IRQ处理程序中。 generic_handle_irq()
来运行处理程序,该处理程序针对每个特定的引脚设置。例如,在omap_gpio_irq_handler()中查看它是如何完成的。现在我们处于MAX7325 IRQ处理程序中。 handle_nested_irq()
,以便连接到MAX7325的设备的所有IRQ处理程序(在本例中为“某些设备” IRQ处理程序)将在max732x_irq_handler()
线程最后,
IRQ域API
GIC驱动程序,GPIO驱动程序和MAX7325驱动程序-它们都使用IRQ域API将这些驱动程序表示为中断 Controller 。让我们看一下如何在MAX732x驱动程序中完成它。它是在this commit中添加的。只需阅读IRQ域文档并查看此提交,就很容易弄清楚它是如何工作的。该提交最有趣的部分是这一行(在
max732x_irq_handler()
中):handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain, level));
irq_find_mapping()
将按硬件IRQ号找到Linux IRQ号(使用IRQ域映射函数)。然后将调用handle_nested_irq()
函数,该函数将运行“某些设备”驱动程序的IRQ处理程序。GPIOLIB_IRQCHIP
由于许多GPIO驱动程序以相同的方式使用IRQ域,因此决定将该代码提取到GPIOLIB框架中,更具体地讲,将其提取到GPIOLIB_IRQCHIP中。从
Documentation/gpio/driver.txt
:This commit在MAX732x驱动程序中将IRQ域API转换为GPIOLIB_IRQCHIP API。
下一个问题
进一步的讨论在这里: