struct of_device_id
{
char name[32];------要匹配的device node的名字
char type[32];-------要匹配的device node的类型
char compatible[128];---匹配字符串(DT compatible string),用来匹配适合的device node
const void *data;--------对于GIC,这里是初始化函数指针
};
这个数据结构主要被用来进行Device node和driver模块进行匹配用的。从该数据结构的定义可以看出,在匹配过程中,device name、device type和DT compatible string都是考虑的因素。更细节的内容请参考__of_device_is_compatible函数。
(2)device node
不同的GIC-V2的实现总会有一些不同,这些信息可以通过Device tree的机制来传递。Device node中定义了各种属性,其中就包括了memory资源,IRQ描述等信息,这些信息需要在初始化的时候传递给具体的驱动,因此需要一个Device node和driver模块的匹配过程。在Device Tree模块中会包括系统中所有的device node,如果我们的系统使用了GIC-400,那么系统的device node中会有一个node是GIC-400的,一个示例性的GIC-400的device node(我们以瑞芯微的RK3288处理器为例)定义如下:
gic: interrupt-controller@ffc01000 {
compatible = "arm,gic-400";
interrupt-controller;
#interrupt-cells = <3>;
#address-cells = <0>;
reg = <0xffc01000 0x1000="">,----Distributor address range
<0xffc02000 0x1000="">,-----CPU interface address range
<0xffc04000 0x2000="">,-----Virtual interface control block
<0xffc06000 0x2000="">;-----Virtual CPU interfaces
interrupts = <gic_ppi 0xf04="" 9="">;
};
(3)device node和irq chip driver的匹配
在machine driver初始化的时候会调用irqchip_init函数进行irq chip driver的初始化。在driver/irqchip/irqchip.c文件中定义了irqchip_init函数,如下:
void __init irqchip_init(void)
{
of_irq_init(__irqchip_begin);
}
__irqchip_begin就是内核irq chip table的首地址,这个table也就保存了kernel支持的所有的中断控制器的ID信息(用于和device node的匹配)。of_irq_init函数执行之前,系统已经完成了device tree的初始化,因此系统中的所有的设备节点都已经形成了一个树状结构,每个节点代表一个设备的device node。of_irq_init是在所有的device node中寻找中断控制器节点,形成树状结构(系统可以有多个interrupt controller,之所以形成中断控制器的树状结构,是为了让系统中所有的中断控制器驱动按照一定的顺序进行初始化)。之后,从root interrupt controller节点开始,对于每一个interrupt controller的device node,扫描irq chip table,进行匹配,一旦匹配到,就调用该interrupt controller的初始化函数,并把该中断控制器的device node以及parent中断控制器的device node作为参数传递给irq chip driver。。具体的匹配过程的代码属于Device Tree模块的内容,更详细的信息可以参考Device Tree代码分析文档。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shumachanpin/article-76887-6.html
能打吗
还鼓励吃激素