void __init gic_init_bases(unsigned int gic_nr, int irq_start,(a)gic_nr标识GIC number,等于0就是root GIC。hwirq的意思就是GIC上的HW interrupt ID,并不是GIC上的每个interrupt ID都有map到linux IRQ framework中的一个IRQ number,对于SGI,是属于软件中断,用于CPU之间通信,没有必要进行HW interrupt ID到IRQ number的mapping。变量hwirq_base表示该GIC上要进行map的base ID,hwirq_base = 16也就意味着忽略掉16个SGI。对于系统中其他的GIC,其PPI也没有必要mapping,因此hwirq_base = 32。
void __iomem *dist_base, void __iomem *cpu_base,
u32 percpu_offset, struct device_node *node)
{
irq_hw_number_t hwirq_base;
struct gic_chip_data *gic;
int gic_irqs, irq_base, i;
gic = &gic_data[gic_nr];
gic->dist_base.common_base = dist_base; ----省略了non banked的情况
gic->cpu_base.common_base = cpu_base;
gic_set_base_accessor(gic, gic_get_common_base);
for (i = 0; i < NR_GIC_CPU_IF; i++) ---后面会具体描述gic_cpu_map的含义
gic_cpu_map = 0xff;
if (gic_nr == 0 && (irq_start & 31) > 0) { --------------------(a)
hwirq_base = 16;
if (irq_start != -1)
irq_start = (irq_start & ~31) + 16;
} else {
hwirq_base = 32;
}
gic_irqs = readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) & 0x1f; ----(b)
gic_irqs = (gic_irqs + 1) * 32;
if (gic_irqs > 1020)
gic_irqs = 1020;
gic->gic_irqs = gic_irqs;
gic_irqs -= hwirq_base;----------------------------(c)
if (of_property_read_u32(node, "arm,routable-irqs",----------------(d)
&nr_routable_irqs)) {
irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, numa_node_id()); -------(e)
if (IS_ERR_VALUE(irq_base)) {
WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
irq_start);
irq_base = irq_start;
}
gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, -------(f)
hwirq_base, &gic_irq_domain_ops, gic);
} else {
gic->domain = irq_domain_add_linear(node, nr_routable_irqs, --------(f)
&gic_irq_domain_ops,
gic);
}
if (gic_nr == 0) { ---只对root GIC操作,因为设定callback、注册Notifier只需要一次就OK了
#ifdef CONFIG_SMP
set_smp_cross_call(gic_raise_softirq);------------------(g)
register_cpu_notifier(&gic_cpu_notifier);------------------(h)
#endif
set_handle_irq(gic_handle_irq); ---这个函数名字也不好,实际上是设定arch相关的irq handler
}
gic_chip.flags |= gic_arch_extn.flags;
gic_dist_init(gic);---------具体的硬件初始代码,参考下节的描述
gic_cpu_init(gic);
gic_pm_init(gic);
}
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |