Linux 中断框架

start_kernel  -----------------init/main.c

      ---->init_IRQ(选择Linux通用初始化函数,还是板子自带初始化函数)-------arch/arm/kernel/irq.c

      ---------->irqchip_init---------------------driver/irqchip/irqchip.c

      ------------------->of_irq_init()-------------driver/of/irq.c

      ===========================================

void __init irqchip_init(void)
{
    of_irq_init(__irqchip_of_table);----------主要通过IRQCHIP_DECLARE(am33xx_intc, "ti,am33xx-intc", intc_of_init)填充在该                                                                             of_device_id结构体中。-------driver/irqchip/xxx.c板级支持文件。如ti的omap系列
    acpi_probe_device_table(irqchip);
}

IRQCHIP_DECLARE--------------include/linux/irqchip.h

#define _OF_DECLARE(table, name, compat, fn, fn_type)            \
    static const struct of_device_id __of_table_##name        \
        __used __section(__##table##_of_table)            \
         = { .compatible = compat,                \
             .data = (fn == (fn_type)NULL) ? fn : fn  }

void __init of_irq_init(const struct of_device_id *matches)
{
    const struct of_device_id *match;
    struct device_node *np, *parent = NULL;
    struct of_intc_desc *desc, *temp_desc;
    struct list_head intc_desc_list, intc_parent_list;

    INIT_LIST_HEAD(&intc_desc_list);
    INIT_LIST_HEAD(&intc_parent_list);

    for_each_matching_node_and_match(np, matches, &match) {
        if (!of_property_read_bool(np, "interrupt-controller") ||
                !of_device_is_available(np))
            continue;

        if (WARN(!match->data, "of_irq_init: no init function for %s\n",
             match->compatible))
            continue;

        /*
         * Here, we allocate and populate an of_intc_desc with the node
         * pointer, interrupt-parent device_node etc.
         */
        desc = kzalloc(sizeof(*desc), GFP_KERNEL);
        if (WARN_ON(!desc)) {
            of_node_put(np);
            goto err;
        }

        desc->irq_init_cb = match->data;
        desc->dev = of_node_get(np);
        desc->interrupt_parent = of_irq_find_parent(np);
        if (desc->interrupt_parent == np)
            desc->interrupt_parent = NULL;
        list_add_tail(&desc->list, &intc_desc_list);
    }

    /*
     * The root irq controller is the one without an interrupt-parent.
     * That one goes first, followed by the controllers that reference it,
     * followed by the ones that reference the 2nd level controllers, etc.
     */
    while (!list_empty(&intc_desc_list)) {
        /*
         * Process all controllers with the current 'parent'.
         * First pass will be looking for NULL as the parent.
         * The assumption is that NULL parent means a root controller.
         */
        list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
            int ret;

            if (desc->interrupt_parent != parent)
                continue;

            list_del(&desc->list);

            of_node_set_flag(desc->dev, OF_POPULATED);

            pr_debug("of_irq_init: init %pOF (%p), parent %p\n",
                 desc->dev,
                 desc->dev, desc->interrupt_parent);
            ret = desc->irq_init_cb(desc->dev,
                        desc->interrupt_parent);--------调用通过IRQCHIP_DECLARE声明的of_device_id->data函数,即intc_of_init

            if (ret) {
                of_node_clear_flag(desc->dev, OF_POPULATED);
                kfree(desc);
                continue;
            }

            /*
             * This one is now set up; add it to the parent list so
             * its children can get processed in a subsequent pass.
             */
            list_add_tail(&desc->list, &intc_parent_list);
        }

        /* Get the next pending parent that might have children */
        desc = list_first_entry_or_null(&intc_parent_list,
                        typeof(*desc), list);
        if (!desc) {
            pr_err("of_irq_init: children remain, but no parents\n");
            break;
        }
        list_del(&desc->list);
        parent = desc->dev;
        kfree(desc);
    }

    list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
        list_del(&desc->list);
        kfree(desc);
    }
err:
    list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
        list_del(&desc->list);
        of_node_put(desc->dev);
        kfree(desc);
    }
}

如上是Linux中断初始化框架,需要具体跟踪如何初始化的可进一步查看板级支持文件。 

参考链接:http://www.wowotech.net/linux_kenrel/gic_driver.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从明天起20200323

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值