原创文章,转载请注明出处:
本文主要分析linux内核中设备驱动程序是如何申请中断的。中断的申请分为两个阶段,接下来分别
对两个阶段进行分析。第一阶段:获取软件中断号,irq = platform_get_irq(pdev, 0)
->of_irq_get(dev->dev.of_node, num); drivers/base/platform.c
{
1. 解析dts中device node对中断的配置,rc = of_irq_parse_one(dev, index, &oirq);
{
以下是dts文件中i2c节点关于中断的定义, 这里主要看软解是如何解析中断的
i2c0: i2c@5a800000
{
interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
};
解析的目的是初始化struct of_phandle_args结构体,该结构体定义如下:
struct of_phandle_args
{
struct device_node *np;
int args_count;
uint32_t args[MAX_PHANDLE_ARGS];
};
解析的结果为:
out_irq->np = interrupt-parent = gic node
out_irq->args[0] = GIC_SPI;
out_irq->args[1] = 硬件中断号 = 220
out_irq->args[2] = 中断触发类型 = IRQ_TYPE_LEVEL_HIGH
}
2. 找到interrupt controller对应的irq domain,对于i2c来说,其对应的中断控制器为gic。
domain = irq_find_host(oirq.np);
{
irq_find_matching_fwspec() kernel/irq/irqdomain.c
{
list_for_each_entry(h, &irq_domain_list, link)
{
rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
((bus_token == DOMAIN_BUS_ANY) ||
(h->bus_token == bus_token)));
if (rc) {
found = h;
break;
}
}
}
从上面的code可知linux kernel是通过匹配irq_domain_list中的fwnode参数来找当前终端控制器对应的
domain, 那么domain又是在什么时候加入irq_domain_list中的呢?
我们还是以跟终端控制器gic为例进行分析,gic在初始化的时候通过下面的函数创建irq domain。
gic->domain = irq_domain_create_linear(handle, gic_irqs,
&gic_irq_domain_hierarchy_ops, gic);
{
新建一个domain
struct irq_domain *domain;
domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
GFP_KERNEL, of_node_to_nid(of_node));
初始化新建的domain
INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
domain->ops = ops;
domain->host_data = host_data;
domain->fwnode = fwnode;