JJJ

编程入门 行业动态 更新时间:2024-10-07 06:45:07

JJJ

JJJ

以imx6u为例:
有两处调用了irq_domain_add_linear向系统注册irq domain 线性映射。没有no_map和Radix_Tree_map这两种方式(irq_domain_add_nomap 和 irq_domain_add_tree)

调用栈2处分别为:

1、

CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.1.15 #1
Hardware name: Freescale i.MX6 Ultralite (Device Tree)
[<80015ed4>] (unwind_backtrace) from [<80012794>] (show_stack+0x10/0x14)
[<80012794>] (show_stack) from [<806f2218>] (dump_stack+0x80/0xc8)
[<806f2218>] (dump_stack) from [<809dc3bc>] (gic_init_bases+0xa4/0x280)
[<809dc3bc>] (gic_init_bases) from [<809dc648>] (gic_of_init+0xb0/0x108)
[<809dc648>] (gic_of_init) from [<809e76ec>] (of_irq_init+0x158/0x278)
[<809e76ec>] (of_irq_init) from [<809a4328>] (init_IRQ+0x28/0x84)
[<809a4328>] (init_IRQ) from [<809a1ac4>] (start_kernel+0x210/0x3a0)
[<809a1ac4>] (start_kernel) from [<8000807c>] (0x8000807c)

2、

CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.1.15 #1
Hardware name: Freescale i.MX6 Ultralite (Device Tree)
[<80015ed4>] (unwind_backtrace) from [<80012794>] (show_stack+0x10/0x14)
[<80012794>] (show_stack) from [<806f2218>] (dump_stack+0x80/0xc8)
[<806f2218>] (dump_stack) from [<80075498>] (irq_domain_add_hierarchy+0x38/0xc8)
[<80075498>] (irq_domain_add_hierarchy) from [<809aec20>] (imx_gpc_init+0xa0/0x2a0)
[<809aec20>] (imx_gpc_init) from [<809e76ec>] (of_irq_init+0x158/0x278)
[<809e76ec>] (of_irq_init) from [<809a4328>] (init_IRQ+0x28/0x84)
[<809a4328>] (init_IRQ) from [<809a1ac4>] (start_kernel+0x210/0x3a0)
[<809a1ac4>] (start_kernel) from [<8000807c>] (0x8000807c)

由start_kernel找到init_IRQ(arch/arm/kernel/irq.c),到irqchip_init(drivers/irqchip/irqchip.c),到of_irq_init(__irqchip_of_table) drivers/of/irq.c

/*** of_irq_init - Scan and init matching interrupt controllers in DT* @matches: 0 terminated array of nodes to match and init function to call** This function scans the device tree for matching interrupt controller nodes,* and calls their initialization functions in order with parents first.*/
void __init of_irq_init(const struct of_device_id *matches)
{struct device_node *np, *parent = NULL;struct 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(np, matches) {// 这个属性位于imx6ull.dtsi中的interrupt-controller@00a01000节点内部if (!of_find_property(np, "interrupt-controller", NULL) ||!of_device_is_available(np))   //节点的status为ok或者okey,或者没有status属性就返回truecontinue;/** Here, we allocate and populate an intc_desc with the node* pointer, interrupt-parent device_node etc.*/desc = kzalloc(sizeof(*desc), GFP_KERNEL);if (WARN_ON(!desc))goto err;desc->dev = 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) {const struct of_device_id *match;int ret;if (desc->interrupt_parent != parent)continue;list_del(&desc->list);match = of_match_node(matches, desc->dev);if (WARN(!match->data,"of_irq_init: no init function for %s\n",match->compatible)) {kfree(desc);continue;}pr_debug("of_irq_init: init %s @ %p, parent %p\n",match->compatible,desc->dev, desc->interrupt_parent);irq_init_cb = (of_irq_init_cb_t)match->data;ret = irq_init_cb(desc->dev, desc->interrupt_parent);if (ret) {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);kfree(desc);}
}

下面是2个struct of_device_id类型的条目,是irq控制器初始化相关:
1、

// drivers/irqchip/irq-gic.c
IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);// drivers/irqchip/irqchip.h
#define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
OF_DECLARE_2(irqchip, cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);//include/linux/of.h
#define OF_DECLARE_2(table, name, compat, fn) \_OF_DECLARE(table, name, compat, fn, of_init_fn_2)_OF_DECLARE(irqchip, cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init, of_init_fn_2)// include/linux/of.h
#define _OF_DECLARE(table, name, compat, fn, fn_type)           \static const struct of_device_id __of_table_##name      \__used __section(__##table##_of_table)          \= { patible = compat,              \.data = (fn == (fn_type)NULL) ? fn : fn  }static const struct of_device_id __of_table_cortex_a7_gic__used __section(__irqchip_of_table)= {patible = "arm,cortex-a7-gic", .data = (gic_of_init == (of_init_fn_2)NULL?gic_of_init:gic_of_init   }通过"arm,cortex-a7-gic"匹配,将match->data赋值给init_urq_cb,即gic_of_init,并执行

2、

// arch/arm/mach-imx/gpc.c
OF_DECLARE_2(irqchip, imx_gpc, "fsl,imx6q-gpc", imx_gpc_init);
...
static const struct of_device_id __of_table_imx_gpc__used __section(__irqchip_of_table)= {patible = "fsl,imx6q-gpc",.data = (imx_gpc_init == (of_init_fn_2)NULL?imx_gpc_init:imx_gpc_init)}

找出这两个compat对应的设备节点:

// imx6ull.dtsi
...
intc: interrupt-controller@00a01000 {compatible = "arm,cortex-a7-gic";#interrupt-cells = <3>;interrupt-controller;reg = <0x00a01000 0x1000>,<0x00a02000 0x100>;};
...gpc: gpc@020dc000 {compatible = "fsl,imx6ul-gpc", "fsl,imx6q-gpc";reg = <0x020dc000 0x4000>;interrupt-controller;#interrupt-cells = <3>;interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;interrupt-parent = <&intc>;fsl,mf-mix-wakeup-irq = <0xfc00000 0x7d00 0x0 0x1400640>;};
...

先看 gic_of_init:在drivers/irqchip/irq-gic.c
gic_of_init

更多推荐

JJJ

本文发布于:2024-02-27 20:55:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1766668.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:JJJ

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!