(e)有些SOC会在各种外设中断和GIC之间增加cross bar(例如TI的OMAP芯片),这里是为那些ARM SOC准备的
(2)gic_irq_domain_unmap是gic_irq_domain_map的逆过程也就是解除IRQ number和GIC hw interrupt ID之间映射关系的时候,需要调用该回调函数。
(3)gic_irq_domain_xlate函数:除了标准的属性之外,各个具体的interrupt controller可以定义自己的device binding。这些device bindings都需在irq chip driver这个层面进行解析。要给定某个外设的device tree node 和interrupt specifier,该函数可以解码出该设备使用的hw interrupt ID和linux irq type value 。具体的代码如下:
static int gic_irq_domain_xlate(struct irq_domain *d,
struct device_node *controller,
const u32 *intspec, unsigned int intsize,--------输入参数
unsigned long *out_hwirq, unsigned int *out_type)----输出参数
{
unsigned long ret = 0;
*out_hwirq = intspec[1] + 16; ---------------------(a)
*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; -----------(b)
return ret;
}
(a)根据gic binding文档的描述,其interrupt specifier包括3个cell,分别是interrupt type(0 表示SPI,1表示PPI),interrupt number(对于PPI,范围是[0-15],对于SPI,范围是[0-987]),interrupt flag(触发方式)。GIC interrupt specifier中的interrupt number需要加上16(也就是加上SGI的那些ID号),才能转换成GIC的HW interrupt ID。
(b)取出bits[3:0]的信息,这些bits保存了触发方式的信息
2、电源管理的callback函数
TODO
3、irq chip回调函数分析
(1)gic_mask_irq函数
这个函数用来mask一个interrupt source。代码如下:
static void gic_mask_irq(struct irq_data *d)
{
u32 mask = 1 << (gic_irq(d) % 32);
raw_spin_lock(&irq_controller_lock);
writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
if (gic_arch_extn.irq_mask)
gic_arch_extn.irq_mask(d);
raw_spin_unlock(&irq_controller_lock);
}
GIC有若干个叫做Interrupt Clear-Enable Registers(具体数目是和GIC支持的hw interrupt数目相关,我们前面说过的,GIC是一个高度可配置的interrupt controller)。这些Interrupt Clear-Enable Registers寄存器的每个bit可以控制一个interrupt source是否forward到CPU interface,写入1表示Distributor不再forward该interrupt,因此CPU也就感知不到该中断,也就是mask了该中断。特别需要注意的是:写入0无效,而不是unmask的操作。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shumachanpin/article-76887-16.html
没用