irq分析之irqchip.c

256 IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic",
257                 bcm2835_armctrl_of_init);
我们来看看IRQCHIP_DECLARE 的定义.
source/include/linux/irqchip.h#L27
 27 #define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
继续看OF_DECLARE_2的实现
 #if defined(CONFIG_OF) 
998 #define _OF_DECLARE(table, name, compat, fn, fn_type)                   \
999         static const struct of_device_id __of_table_##name              \
1000                 __used __section(__##table##_of_table)                  \
1001                  = { .compatible = compat,                              \
1002                      .data = (fn == (fn_type)NULL) ? fn : fn  }
1003 #else
1004 #define _OF_DECLARE(table, name, compat, fn, fn_type)                   \
1005         static const struct of_device_id __of_table_##name              \
1006                 __attribute__((unused))                                 \
1007                  = { .compatible = compat,                              \
1008                      .data = (fn == (fn_type)NULL) ? fn : fn }
1009 #endif
1010 
1011 typedef int (*of_init_fn_2)(struct device_node *, struct device_node *);
1012 typedef void (*of_init_fn_1)(struct device_node *);
1013 
1014 #define OF_DECLARE_1(table, name, compat, fn) \
1015                 _OF_DECLARE(table, name, compat, fn, of_init_fn_1)
1016 #define OF_DECLARE_2(table, name, compat, fn) \
1017                 _OF_DECLARE(table, name, compat, fn, of_init_fn_2)


在实际使用过程中CONFIG_OF 是定义.
所以OF_DECLARE_2 是1016行的宏_OF_DECLARE来实现的。
再来看999行_OF_DECLARE的实现。有OF_DECLARE_2的第一个参数是table,而在27行table被定义irqchip。所以1000行的section就是irqchip_of_able。
所以256行的bcm2835_armctrl_of_init是被放在irqchip_of_able 中.
明白上面后我们来看irqchip.c的实现.
/drivers/irqchip/irqchip.c
 22 static const struct of_device_id
 23 irqchip_of_match_end __used __section(__irqchip_of_table_end);
 24 
 25 extern struct of_device_id __irqchip_of_table[];
 26 
 27 void __init irqchip_init(void)
 28 {
 29         of_irq_init(__irqchip_of_table);
 30         acpi_probe_device_table(irqchip);
 31 }
而irqchip_init 是被init_IRQ 调用的。而init_IRQ是被 start_kernel调用的,也就是kernel 会在刚开始的初始化函数中调用.
 void __init init_IRQ(void)
 22 {
 23         /*
 24          * process the entire interrupt tree in one go
 25          * Any external intc will be setup provided DT chains them
 26          * properly
 27          */
 28         irqchip_init();
 38 }


调用flow清楚了,我们在来看看of_irq_init 这个函数主要scan和init 匹配的interrupt controller.
这个函数的实现如下:
从500开始找interrupt-controller node。
如果找到,则在512行申请一个of_intc_desc 
518行保存irq_init_cb,就是在上面分析的bcm2835_armctrl_of_init
从531开始的循环中主要就是调用bcm2835_armctrl_of_init函数,具体是在548   ret = desc->irq_init_cb(desc->dev,desc->interrupt_parent);调用


489 void __init of_irq_init(const struct of_device_id *matches)
490 {
491         const struct of_device_id *match;
492         struct device_node *np, *parent = NULL;
493         struct of_intc_desc *desc, *temp_desc;
494         struct list_head intc_desc_list, intc_parent_list;
495 
496         INIT_LIST_HEAD(&intc_desc_list);
497         INIT_LIST_HEAD(&intc_parent_list);
498 
499         for_each_matching_node_and_match(np, matches, &match) {
500                 if (!of_find_property(np, "interrupt-controller", NULL) ||
501                                 !of_device_is_available(np))
502                         continue;
503 
504                 if (WARN(!match->data, "of_irq_init: no init function for %s\n",
505                          match->compatible))
506                         continue;
507 
508                 /*
509                  * Here, we allocate and populate an of_intc_desc with the node
510                  * pointer, interrupt-parent device_node etc.
511                  */
512                 desc = kzalloc(sizeof(*desc), GFP_KERNEL);
513                 if (WARN_ON(!desc)) {
514                         of_node_put(np);
515                         goto err;
516                 }
517 
518                 desc->irq_init_cb = match->data;
519                 desc->dev = of_node_get(np);
520                 desc->interrupt_parent = of_irq_find_parent(np);
521                 if (desc->interrupt_parent == np)
522                         desc->interrupt_parent = NULL;
523                 list_add_tail(&desc->list, &intc_desc_list);
524         }
525 
526         /*
527          * The root irq controller is the one without an interrupt-parent.
528          * That one goes first, followed by the controllers that reference it,
529          * followed by the ones that reference the 2nd level controllers, etc.
530          */
531         while (!list_empty(&intc_desc_list)) {
532                 /*
533                  * Process all controllers with the current 'parent'.
534                  * First pass will be looking for NULL as the parent.
535                  * The assumption is that NULL parent means a root controller.
536                  */
537                 list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
538                         int ret;
539 
540                         if (desc->interrupt_parent != parent)
541                                 continue;
542 
543                         list_del(&desc->list);
544 
545                         pr_debug("of_irq_init: init %s (%p), parent %p\n",
546                                  desc->dev->full_name,
547                                  desc->dev, desc->interrupt_parent);
548                         ret = desc->irq_init_cb(desc->dev,
549                                                 desc->interrupt_parent);
550                         if (ret) {
551                                 kfree(desc);
552                                 continue;
553                         }
554 
555                         /*
556                          * This one is now set up; add it to the parent list so
557                          * its children can get processed in a subsequent pass.
558                          */
559                         list_add_tail(&desc->list, &intc_parent_list);
560                 }
561 
562                 /* Get the next pending parent that might have children */
563                 desc = list_first_entry_or_null(&intc_parent_list,
564                                                 typeof(*desc), list);
565                 if (!desc) {
566                         pr_err("of_irq_init: children remain, but no parents\n");
567                         break;
568                 }
569                 list_del(&desc->list);
570                 parent = desc->dev;
571                 kfree(desc);
572         }
573 
574         list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
575                 list_del(&desc->list);
576                 kfree(desc);
577         }
578 err:
579         list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
580                 list_del(&desc->list);
581                 of_node_put(desc->dev);
582                 kfree(desc);
583         }
584 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值