Linux内核中可使用platform_get_irq()函数获取dts文件中设置的中断号。

函数原型:int platform_get_irq(struct platform_device *dev, unsigned int num)

定义文件:drivers\base\platform.c

一、调用流程

中断号获取函数platform_get_irq()调用流程如下:

platform_get_irq()->

of_irq_get()->

of_irq_parse_one() ## 解析dts中中断相关属性,填充结构体of_phandle_args中的args[]参数

irq_create_of_mapping()->

of_phandle_args_to_fwspec() ## 将of_phandle_args->args[]赋值给fwspec->param[],给translate使用

irq_create_fwspec_mapping()->

irq_domain_translate()-> ## 获取中断号和中断触发类型

translate()-> ## 对应某个版本的gic处理函数

rk3399使用的是GICv3,对应irq_domain->name。

文件:drivers/irqchip/irq-gic-v3.c。

translate()函数实现如下:

static const struct irq_domain_ops gic_irq_domain_ops = {

.translate = gic_irq_domain_translate, ## .translate的实现函数

...

};

static int gic_irq_domain_translate(struct irq_domain *d,

struct irq_fwspec *fwspec,

unsigned long *hwirq,

unsigned int *type)

{

...

switch (fwspec->param[0]) {

case 0: /* SPI */

*hwirq = fwspec->param[1] + 32; ## 中断号

break;

case 1: /* PPI */

*hwirq = fwspec->param[1] + 16; ## 中断号

break;

case GIC_IRQ_TYPE_LPI: /* LPI */

*hwirq = fwspec->param[1]; ## 中断号

break;

default:

return -EINVAL;

}

*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; ## 中断触发类型

...

}

二、应用举例

以RockPI 4A单板Debian系统Linux 4.4内核中的获取HDMI中断号为例。

1、查找中断号

从手册“Rockchip RK3399 TRM V1.3 Part1.pdf”中,可以查到HDMI_IRQ中断号,即55。

471f3273333c

RK3399中断

2、dts配置

文件:arch/arm64/boot/dts/rockchip/rk3399.dtsi

hdmi: hdmi@ff940000 {

compatible = "rockchip,rk3399-dw-hdmi";

...

interrupts = ;

...

}

hdmi使用的是GIC_SPI中断,按照gic_irq_domain_translate()函数中处理,需要将中断号55减去32,得到dts中的中断号23。

注:interrupts =

3、驱动函数

文件:drivers\gpu\drm\rockchip\dw_hdmi-rockchip.c

static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,

void *data)

{

...

irq = platform_get_irq(pdev, 0);

...

}

此时,irq返回值为55。

后续会介绍GIC和中断注册等实现函数。

Logo

更多推荐