1. 程式人生 > >LInux-3.0.8中基於S5PV210的IRQ模塊代碼追蹤和分析

LInux-3.0.8中基於S5PV210的IRQ模塊代碼追蹤和分析

PV 塊代碼 smd 函數定義 void 全局 對數 radix ali

init/main.c:

1 asmlinkage void start_kernel(void)
2 {
3     ......
4     early_irq_init();
5     init_IRQ();
6     ......
7 }

early_irq_init()函數有兩種實現,一種是基於radix tree,一種是定義靜態數組,如果要使用radix tree實現的,那麽需要打開SPARSE_IRQ配置選項,由於我對數據結構不了解,所以分析以下靜態數組實現方式版本的。

/kernel/irq/irqdesc.c

 1 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
2 [0 ... NR_IRQS-1] = { 3 .handle_irq = handle_bad_irq, 4 .depth = 1, 5 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), 6 } 7 }; 8 9 int __init early_irq_init(void) 10 { 11 int count, i, node = first_online_node; 12 struct irq_desc *desc;
13 14 init_irq_default_affinity(); 15 16 printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS); 17 18 desc = irq_desc; 19 count = ARRAY_SIZE(irq_desc); 20 21 for (i = 0; i < count; i++) { 22 desc[i].kstat_irqs = alloc_percpu(unsigned int); 23 alloc_masks(&desc[i], GFP_KERNEL, node);
24 raw_spin_lock_init(&desc[i].lock); 25 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); 26 desc_set_defaults(i, &desc[i], node); 27 } 28 return arch_early_irq_init(); 29 }

  第一次見到這種初始化數組全部成員為同樣內容的方式,可以學習積累下。

  NR_IRQS在arch/arm/mach-s5pv210/include/mach/irqs.h下定義:

1 #define NR_IRQS            (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)

  上面函數的核心就是調用desc_set_defaults()來初始化上述中斷描述符數組,kernel/irq/irqdesc.c:

 1 static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
 2 {
 3     int cpu;
 4 
 5     desc->irq_data.irq = irq;
 6     desc->irq_data.chip = &no_irq_chip;
 7     desc->irq_data.chip_data = NULL;
 8     desc->irq_data.handler_data = NULL;
 9     desc->irq_data.msi_desc = NULL;
10     irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
11     irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);
12     desc->handle_irq = handle_bad_irq;
13     desc->depth = 1;
14     desc->irq_count = 0;
15     desc->irqs_unhandled = 0;
16     desc->name = NULL;
17     for_each_possible_cpu(cpu)
18         *per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
19     desc_smp_init(desc, node);
20 }

  最後返回時調用的arch_early_irq_init()函數並沒有做事情。

  接著看init_IRQ():

1 void __init init_IRQ(void)
2 {
3     machine_desc->init_irq();
4 }

  machine_desc是全局變量,定義在板文件中,由於我們使用的是s5pv210,且demo板號選的是smdkv210,所以這個全局變量就在arch/arm/mach-s5pv210/mach-s5pv210.c中:

1 MACHINE_START(SMDKV210, "SMDKV210")
2     /* Maintainer: Kukjin Kim <[email protected]> */
3     .boot_params    = S5P_PA_SDRAM + 0x100,
4     .init_irq    = s5pv210_init_irq,
5     .map_io        = smdkv210_map_io,
6     .init_machine    = smdkv210_machine_init,
7     .timer        = &s5p_timer,
8 MACHINE_END

arch/arm/mach-s5pv210/mach-s5pv210.c中還有如下函數定義:

 1 void __init s5pv210_init_irq(void)
 2 {
 3     u32 vic[4];    /* S5PV210 supports 4 VIC */
 4 
 5     /* All the VICs are fully populated. */
 6     vic[0] = ~0;
 7     vic[1] = ~0;
 8     vic[2] = ~0;
 9     vic[3] = ~0;
10 
11     s5p_init_irq(vic, ARRAY_SIZE(vic));
12 }

arch/arm/plat-s5p/irq.c

 1 void __init s5p_init_irq(u32 *vic, u32 num_vic)
 2 {
 3 #ifdef CONFIG_ARM_VIC
 4     int irq;
 5 
 6     /* initialize the VICs */
 7     for (irq = 0; irq < num_vic; irq++)
 8         vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
 9 #endif
10 
11     s3c_init_vic_timer_irq(5, IRQ_TIMER0);
12 
13     s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
14 }

  上面涉及到的函數都是去操作VIC相關的寄存器,這部分操作還不是很清楚,先不往下繼續追蹤了。

LInux-3.0.8中基於S5PV210的IRQ模塊代碼追蹤和分析