5、在设备树中指定中断——在代码中获取中断

1 设备树里中断节点的语法
参考文档:
内核 Documentation\devicetree\bindings\interrupt-controller\interrupts.txt
设备树里的中断控制器
中断的硬件框图如下:

 在硬件上,“中断控制器”只有 GIC 这一个,但是我们在软件上也可以把上图中的“ GPIO”称为“中断控制器”。很多芯片有多个 GPIO 模块,比如 GPIO1GPIO2 等等。所以软件上的“中断控制器”就有很多个: GICGPIO1GPIO2 等等。

GPIO1 连接到 GICGPIO2 连接到 GIC,所以 GPIO1 的父亲是 GICGPIO2的父亲是 GIC

假设 GPIO1 32 个中断源,但是它把其中的 16 个汇聚起来向 GIC 发出一个中断,把另外 16 个汇聚起来向 GIC 发出另一个中断。这就意味着 GPIO1 会用到 GIC 的两个中断,会涉及 GIC 里的 2 hwirq

这些层级关系、中断号(hwirq),都会在设备树中有所体现。

在设备树中,中断控制器节点中必须有一个属性: interrupt-controller,表明它是“中断控制器”。

还必须有一个属性: #interrupt-cells,表明引用这个中断控制器的话需要多少个 cell
#interrupt-cells 的值一般有如下取值:

#interrupt-cells=<1>

别的节点要使用这个中断控制器时,只需要一个 cell 来表明使用“哪一个中断”。

#interrupt-cells=<2>

别的节点要使用这个中断控制器时,需要一个 cell 来表明使用“哪一个中断”;还需要另一个 cell 来描述中断,一般是表明触发类型:

示例如下:

 如 果 中 断 控 制 器 有 级 联 关 系 , 下 级 的 中 断 控 制 器 还 需 要 表 明 它 的“ interrupt-parent ” 是 谁 , 用 了 interrupt-parent ” 中 的 哪 一 个“ interrupts”,请看下一小节。

设备树里使用中断

一个外设,它的中断信号接到哪个“中断控制器”的哪个“中断引脚”,这个中断的触发方式是怎样的?

3 个问题,在设备树里使用中断时,都要有所体现。

interrupt-parent=<&XXXX>

你要用哪一个中断控制器里的中断?

interrupts

你要用哪一个中断?

Interrupts 里要用几个 cell,由 interrupt-parent 对应的中断控制器决定。在中断控制器里有“ #interrupt-cells”属性,它指明了要用几个 cell来描述中断。比如:

 新写法: interrupts-extended

一个“ interrupts-extended”属性就可以既指定“ interrupt-parent”,也指定“ interrupts”,比如:

interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;

2 设备树里中断节点的示例
100ASK_IMX6ULL 开发板为例,在 arch/arm/boot/dts 目录下可以看到2 个文件: imx6ull.dtsi100ask_imx6ull-14x14.dts,把里面有关中断的部分内容抽取出来。

 从设备树反推 IMX6ULL 的中断体系,如下,比之前的框图多了一个“ GPC INTC”:

 GPC INTC 的 英 文 是 : General Power Controller, Interrupt Controller。它提供中断屏蔽、中断状态查询功能,实际上这些功能在 GIC 里也实现了,个人觉得有点多余。除此之外,它还提供唤醒功能,这才是保留它的原因。

3 在代码中获得中断
之 前 我 们 提 到 过 , 设 备 树 中 的 节 点 有 些 能 被 转 换 为 内 核 里 的platform_device,有些不能,回顾如下:

  • 根节点下含有 compatile 属性的子节点,会转换为 platform_device
  • 含有特定 compatile 属性的节点的子节点,会转换为 platform_device

如果一个节点的 compatile 属性,它的值是这 4 者之一: "simplebus","simple-mfd","isa","arm,amba-bus",

那么它的子结点(需含 compatile 属性)也可以转换为 platform_device

  • 总线 I2CSPI 节点下的子节点: 不转换platform_device

某个总线下到子节点, 应该交给对应的总线驱动程序来处理, 它们不应该被转换为 platform_device


对于 platform_device

一个节点能被转换为 platform_device,如果它的设备树里指定了中断属性,那么可以从 platform_device 中获得“中断资源”,函数如下,可以使用下列函数获得 IORESOURCE_IRQ 资源,即中断号:

 对于 I2C 设备、 SPI 设备

对于 I2C 设备节点, I2C 总线驱动在处理设备树里的 I2C 子节点时,也会处理其中的中断信息。一个 I2C 设备会被转换为一个 i2c_client 结构体,中断号会保存在 i2c_client irq 成员里,代码如下(drivers/i2c/i2c-core.c)

 对于 SPI 设备节点, SPI 总线驱动在处理设备树里的 SPI 子节点时,也会处理其中的中断信息。一个 SPI 设备会被转换为一个 spi_device 结构体,中断号会保存在 spi_device irq 成员里,代码如下(drivers/spi/spi.c)

 

 调用 of_irq_get 获得中断号

如果你的设备节点既不能转换为 platform_device,它也不是 I2C 设备,不是 SPI 设备,那么在驱动程序中可以自行调用 of_irq_get 函数去解析设备树,得到中断号。

 

对于 GPIO

参考: drivers/input/keyboard/gpio_keys.c

可以使用 gpio_to_irq gpiod_to_irq 获得中断号。举例,假设在设备树中有如下节点:

 

 

 





 




posted on 2024-10-07 16:37  拉风摊主  阅读(105)  评论(0编辑  收藏  举报

导航